When I inset a table into a XWPFDocument using an XMLCursor it is inserting the table into the correct position but it is adding an extra box under the first column. The box is joined onto the table so it looks like it is an additional table cell but when I insert the table without using and XMLCursor the table is correct and the box is at the position of the XMLCursor. Is there any way to delete the box as it looks like its an additional table cell.
XWPFDocument part1Document = new XWPFDocument(part1Package);
XmlCursor xmlCursor = part1Document.getDocument().getBody().getPArray(26).newCursor();
//create first row
XWPFTable tableOne = part1Document.createTable();
XWPFTableRow tableOneRowOne = tableOne.getRow(0);
tableOneRowOne.getCell(0).setText("Hello");
tableOneRowOne.addNewTableCell().setText("World");
XWPFTableRow tableOneRowTwo = tableOne.createRow();
tableOneRowTwo.getCell(0).setText("This is");
tableOneRowTwo.getCell(1).setText("a table");
tableOne.getRow(1).getCell(0).setText("only text");
XmlCursor c2 = tableOne.getCTTbl().newCursor();
c2.moveXml(xmlCursor);
c2.dispose();
XWPFTable tables = part1Document.insertNewTbl(xmlCursor);
xmlCursor.dispose();
The empty box is appearing at the position of the 26th paragraph. Any help would be great. Thanks.
What you do is you actually create two different tables. The first one with method createTable(), then you add rows and cells needed. After that at the cursor on your table tableOneyou create a new table with method insertNewTbl(xmlCursor). The method creates a new table with 1 row and 1 cell, hence your empty box.
I can't say why your first table is actually placed in the correct position, probably because it is merged with the second table, that goes to your cursor.
I suggest you create the second table from the start:
XWPFTable tableOne = part1Document.insertNewTbl(xmlCursor);
XWPFTableRow tableOneRowOne = tableOne.getRow(0);
tableOneRowOne.getCell(0).setText("Hello");
tableOneRowOne.addNewTableCell().setText("World");
Related
A looking for a way to get specific columns by name from several tables. My data comes in several sheets with different number of columns upto 38 columns so i cannot use getColumnById. I only need 7 columns from this.
First am converting all sheet ranges to tables, then am getting all tables.
What I want is to get specific columns by names and merge all into one table on a new sheet.
I followed example from Docs but am stuck at getting column name for each Table.
I know my header Values, shown in example below.
function main(workbook: ExcelScript.Workbook) {
let sheets = workbook.getWorksheets();
for (let sheet of sheets) {
sheet.getTables()[0].convertToRange();
sheet.addTable(sheet.getRange('A1').getUsedRange().getAddress(),true)
}
workbook.getWorksheet('Combined')?.delete();
const newSheet = workbook.addWorksheet('Combined');
const tables = workbook.getTables();
const headerValues = [['Column1', 'Column6', 'Column8', 'Column9','Column11', 'Column16', 'Column18', 'Column19']];
const targetRange = newSheet.getRange('A1').getResizedRange(headerValues.length - 1, headerValues[0].length - 1);
targetRange.setValues(headerValues);
const combinedTable = newSheet.addTable(targetRange.getAddress(), true);
for (let table of tables) {
let dataValues = table.getColumnByName( // this where am stuck //).getRangeBetweenHeaderAndTotal().getTexts();
let rowCount = table.getRowCount();
// If the table is not empty, add its rows to the combined table.
if (rowCount > 0) {
combinedTable.addRows(-1, dataValues);
}
}
}
Thanks for your help.
George
A few things:
In most circumstances for this scenario, I'd recommend iterating
through a specific set of table objects. Unfortunately, that's
difficult to do here. Every time you unlink and recreate a new table,
Excel may give your table a new name. That makes it difficult to
work with the table. You can get around this in your code by
capturing the table name before you unlink it, unlinking the table,
recreating the table, and setting the table name to the original one
captured. If you go that route then you could reliably work with the
table names
Because table names in this scenario can be a bit tricky, I'm going
to use the sheet names so that I can work with the sheets that contain
the underlying tables. This will allow us to use and get data from the
tables regardless of what they're named in the sheets.
Please see my code below:
function main(workbook: ExcelScript.Workbook) {
//JSON object called SheetAndColumnNames. On the left hand side is the sheet name.
//On the right hand side is an array with the column names for the table in the sheet.
//NOTE: replace the sheet and column names with your own values
let columnNames : string[] = ["ColA","ColB","ColC"]
const sheetAndColumnNames = {
"Sheet1": columnNames,
"Sheet2": columnNames
}
//JSON object called columnNamesAndCellValues. On the left hand side is the column name.
//On the right hand side is an array that will hold the values for the column in the table.
//NOTE: replace these column names with your own values
const columnNamesAndCellValues = {
"ColA": [],
"ColB": [],
"ColC": []
}
//Iterate through the sheetAndColumnNames object
for (let sheetName in sheetAndColumnNames) {
//Use sheet name from JSON object to get sheet
let sheet: ExcelScript.Worksheet = workbook.getWorksheet(sheetName)
//get table from the previously assigned sheet
let table: ExcelScript.Table = sheet.getTables()[0]
//get array of column names to be iterated on the sheet
let tableColumnNames: string[] = sheetAndColumnNames[sheetName]
//Iterate the array of table column names
tableColumnNames.forEach(columnName=> {
//get the dataBodyRange of the tableColumn
let tableColumn : ExcelScript.Range = table.getColumn(columnName).getRangeBetweenHeaderAndTotal()
//iterate through all of the values in the table column and add them to the columnNamesAndCellValues array for that column name
tableColumn.getValues().forEach(value=>{
columnNamesAndCellValues[columnName].push(value)
})
})
}
//Delete previous worksheet named Combined
workbook.getWorksheet("Combined")?.delete()
//Add new worksheet named Combined and assign to combinedSheet variable
let combinedSheet : ExcelScript.Worksheet = workbook.addWorksheet("Combined")
//Activate the combined sheet
combinedSheet.activate()
//get the header range for the table
let headerRange : ExcelScript.Range = combinedSheet.getRangeByIndexes(0,0,1,columnNames.length)
//set the header range to the column headers
headerRange.setValues([columnNames])
//iterate through the arrays returned by the columnNamesAndCellValues object to write to the Combined sheet
columnNames.forEach((column,index)=>{
combinedSheet.getRangeByIndexes(1, index, columnNamesAndCellValues[column].length, 1).setValues(columnNamesAndCellValues[column])
})
//Get the address for the current region of the data written from the tableColumnData array to the sheet
let combinedTableAddress : string = combinedSheet.getRange("A1").getSurroundingRegion().getAddress()
//Add the table to the sheet using the address and setting the hasHeaders boolean value to true
combinedSheet.addTable(combinedTableAddress,true)
}
Below is my example code:
db = QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('book.db')
db.open()
model = QSqlQueryModel()
model.setQuery("SELECT * FROM card")
self.tableView.setModel(model)
I am using QSqlQueryModel, Qtablevie, Sqlite3, and able to view all rows in my table. But i want to view only last two rows of my table which are newly inserted rows in to the table. The table has no "id" field and it has numaric and text fields. How is it possible?
Below is the table image:
If you want to get the last 2 elements ordered by any field that indicates the insertion order, in your case "rowid", then you have to use a filter in the SQL command like this:
model.setQuery("SELECT * FROM card ORDER BY rowid DESC LIMIT 2")
Another possible option is to filter the table using QSortFilterProxyModel but it is more inefficient.
Is it possible to update column position with Tabulator?
Or is there a way to do it?
Apparently there is no function to do it.
A moveColumn function will be coming in the 4.2 release next week.
In the mean time you can easily change the order of columns in the table by calling the deleteColumn function and then the addColumn function.
//remove column
table.deleteColumn("age");
//add column elsewhere in the table after the name column
table.addColumn({title:"Age", field:"age"}, "name");
or by changing the column definition array and resubmitting it using the setColumns function
//define new column layout
var columns = [
{title:"Name", field:"name"},
{title:"Age", field:"age"},
{title:"Gender", field:"gender"},
]
//replace all columns
table.setColumns(columns);
Full documentation on these features can be found in the Columns Documentation
I am trying to identify controls at runtime by adding some search properties in my code as and when required. Using Coded UI in Visual Studio 2012.
Please refer to the screenshot below. My test scenario is:
1) Click on a particular tab (the 2nd tab selected in the screenshot)
The Tab list is fixed so I can create one control in My UIMap for each tab.
2) Inside every Tab, there is a tabular structure with some data. The Table headings are fixed but the number of rows and the data inside the rows is dynamic.
3) Check the checkBox for the required tag
4) Select Type for required tag
I have created my UIMap as:
Added following code:
UIEquipmentTagText.SearchProperties.Add(new PropertyExpression(WpfText.PropertyNames.Name, "1302"));// say I want second row
To fetch the respective checkbox control, I am using:
UITestControl UIEquipmentTagCell = UIEquipmentTagText.GetParent();//get the cell of Tag name
UITestControl UIEquipmentTagRow = UIEquipmentTagCell.GetParent();//get the row
UITestControl UIEquipmentCheckBoxCell = UIEquipmentTagRow.GetChildren()[0];//get the first cell i.e the checkbox cell
UITestControl UIEquipmentCheckBox = UIEquipmentCheckBoxCell.GetChildren()[0]; // get the checkbox control
But this is not working for me. I guess the UIRow control is referring to first row only (though I haven’t specified to look for 1st row)
I do not want to include row number in my search criteria for Row.
Is there any workaround to get all the controls I want based on the Tag Text only?
figured out a solution finally..get all rows and iterate to find the matching row
UITestControlCollection allRows = row.FindMatchingControls();
foreach (UITestControl x in allRows)
{
UITestControl Tag = x.GetChildren()[1].GetChildren()[0];//row->tag cell->tag text
if (Tag.GetProperty("Name").Equals("1302"))//say I want to select row having 1302 tag
{
UITestControl checkBox = Tag.GetParent().GetParent().GetChildren()[0].GetChildren()[0];//TagText->TagCell->Row->CheckBoxCell->Checkbox
Mouse.Click(checkBox);
}
}
In the control properties, new row has name equals to Volume Row 62 and Row Index equals to 61 - as recorded and add values in few columns.
When I insert a new row with external data and fill the respective columns, it tries to override the column data in the row which was used in the recording and not the one that is being inserted.
If i remove the 62 and 61 from the Row Properties and make that general, it goes to the first row in the grid and tries to edit.
What properties should be changed or searched for so that columns is populated correctly in the the new row (whose name and row index is not known).
any help is appreciated.
Thanks.
To solve this in our application we exported the UI map method and created a temp list using VAR I don't know if this will work for you or not but solved several of our issues around dynamic grid rows and columns:
public void DoubleClickLaunch_UOW()
{
var temp = this.UIWindow.UIUnitGridTable.GetChildren().ToList();
temp.RemoveAt(0);
var rows = temp.Select(t => t.GetChildren().Select(s => s.GetValue()).ToList()).ToList();
var tractLetters = rows.Select(s => s[1]).ToList();
var index = tractLetters.IndexOf(DoubleClickLaunch_UOWParams.UITESTUNIT_TPText);
if (index >= 0)
{
var textbox = temp[index].GetChildren()[1].GetChildren()[0];
Mouse.DoubleClick(textbox);
}
else
{
Mouse.DoubleClick(this.UIWindow.UIUnitGridTable.UIItemRow.UIUnitNameCell.UITESTUNIT_TPText);
}