Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
ERROR: Getting output table show some blank rows in each column after the first column.
This code works as, there is 4 checkboxlist each of it containing 4 list item. When selecting each of the list item it should be displayed in the
specified column .
Right Output: Each column with specified rows in the right position
private void button1_Click(object sender, EventArgs e)
{
Form2 fm = new Form2();
DataTable dt = new DataTable();
dt.TableName = "FoodOrder";
dt.Clear();
dt.Columns.Add("WelcomeDrinks");
dt.Columns.Add("Starter");
dt.Columns.Add("MainMeals");
dt.Columns.Add("Desserts");
for (int i = 0; i < chk1.Items.Count; i++)
{
if (chk1.GetItemChecked(i))
{
DataRow row = dt.NewRow();
row["WelcomeDrinks"] = (string)chk1.Items[i];
dt.Rows.Add(row);
}
}
for (int i = 0; i < chk2.Items.Count; i++)
{
if (chk2.GetItemChecked(i))
{
DataRow workrow = dt.NewRow();
workrow["Starter"] = (string)chk2.Items[i];
dt.Rows.Add(workrow);
}
}
for (int i = 0; i < chk3.Items.Count; i++)
{
if (chk3.GetItemChecked(i))
{
DataRow row = dt.NewRow();
row["MainMeals"] = (string)chk3.Items[i];
dt.Rows.Add(row);
}
}
for (int i = 0; i < chk4.Items.Count; i++)
{
if (chk4.GetItemChecked(i))
{
DataRow row = dt.NewRow();
row["Desserts"] = (string)chk4.Items[i];
dt.Rows.Add(row);
}
}
fm.Grid1.DataSource = dt;
fm.Show();
}
You are neglecting to take into account how many rows you need in the table. Using your current approach where a new row is added for each checked box item in each check box list, then you end up such that only ONE item will be on each row. The first check box items will have their own row and so will each check box list. It may look something like…
Welcome Drinks Starter MainMeal Desserts
Welcome Drinks 1
Welcome Drinks 2
Starter1
Starter3
Main Meal 1
Main Meal 4
Dessert 3
Dessert 4
Is what you need to do is check each CheckedListBox and figure out which check box list has the GREATEST number of items checked. This will tell you how many rows you need in the table. Then, instead of “adding” new rows in the for loops through each list, simply add the item to the existing row using the column name to determine which cell the value goes in.
To get the list check box with the greatest number of “checked” items may look something like…
int maxRows = chk1.CheckedItems.Count;
if (chk2.CheckedItems.Count > maxRows)
maxRows = chk2.CheckedItems.Count;
if (chk3.CheckedItems.Count > maxRows)
maxRows = chk3.CheckedItems.Count;
if (chk4.CheckedItems.Count > maxRows)
maxRows = chk4.CheckedItems.Count;
Then add that number of rows to the table.
for (int i = 0; i < maxRows; i++) {
dt.Rows.Add();
}
Now the table should have the proper number of columns and rows.
Since we know we have to loop through each CheckedListBox to get the “checked” items, it may help if we create a method that takes a string for the column name we want to put the values, the CheckedListBox and the DataTable and returns nothing.
This AddColumnData method, would loop through each of the “checked” items in the given CheckedListBox and add the items to the data table starting on the first row and the given column name. This method may look something like…
private void AddColumnData(string colName, CheckedListBox checkedListBox, DataTable dt) {
int curRowIndex = 0;
DataRow row;
foreach (var checkedItem in checkedListBox.CheckedItems) {
row = dt.Rows[curRowIndex++];
row[colName] = checkedItem;
}
}
With this method, it will make it easier to add the items to the table as shown below…
AddColumnData("WelcomeDrinks", chk1, dt);
AddColumnData("Starter", chk2, dt);
AddColumnData("MainMeals", chk3, dt);
AddColumnData("Desserts", chk4, dt);
I hope this makes sense.
Related
I am trying to loop through rows within a spreadsheet and identify if a particular row has the key word "hello" and move that entire row into a new spreadsheet.
I have attempted the following code. The code works for the first row but doesn't loop through and stops after the first row. Expanding the range selection to "C1:E32" does not help.
function Edit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activatedSheetName = ss.getActiveSheet().getName();
var ActiveSheet = ss.getSheetByName("ActiveSheet"); // source sheet
var MoveDatatoThisSheet = ss.getSheetByName("MoveDatatoThisSheet"); // target sheet
var re = new RegExp(/(Hello)/i);
var startRow = 1;
var endRow = ss.getLastRow();
var getRange = ss.getDataRange();
var getRow = getRange.getRow();
for (var ree = startRow; ree <= endRow; ree++) {
// if the value in column D is "Approved", move the row to target sheet
cellValue = ss.getRange("C1:E1");
if (cellValue.getValue().match(re)) {
// insert a new row at the second row of the target sheet
MoveDatatoThisSheet.insertRows(2, 1);
// move the entire source row to the second row of target sheet
var rangeToMove = ActiveSheet.getRange(/*startRow*/ getRow, /*startColumn*/ 1, /*numRows*/ 1, /*numColumns*/ ActiveSheet.getMaxColumns());
rangeToMove.moveTo(MoveDatatoThisSheet.getRange("A2"));
// add date and time of when approved to target row in column E
MoveDatatoThisSheet.getRange("E2").setValue(Date());
// delete row from source sheet
ActiveSheet.deleteRow(cellValue, 1);
}
}
}
Your loop never uses the variable ree, it only operates with cellValue = ss.getRange("C1:E1").
Another problem is that deletion shifts the rows under the deleted one, possibly causing subsequent operations to act on a wrong row. When you go through an array of rows, deleting some of them, do it bottom up, not top down.
for (var ree = endRow; ree >= startRow; ree--) {
var rangeToCheck = ss.getRange(ree, 3, 1, 3); // 3 columns starting with column 3, so C-E range
if (rangeToCheck.getValues()[0].join().match(re)) { // joining values before checking the expression
MoveDatatoThisSheet.insertRows(2,1);
var rangeToMove = ActiveSheet.getRange(/*startRow*/ getRow, /*startColumn*/ 1, /*numRows*/ 1, /*numColumns*/ ActiveSheet.getMaxColumns());
rangeToMove.moveTo(MoveDatatoThisSheet.getRange("A2"));
// add date and time of when approved to target row in column E
MoveDatatoThisSheet.getRange("E2").setValue(Date());
// delete row from source sheet
ActiveSheet.deleteRow(ree);
}
}
If the goal is to check only column D (say), the code simplifies slightly
var rangeToCheck = ss.getRange(ree, 4); // column D in row ree
if (rangeToCheck.getValue().match(re)) { // joining values before checking the expression
Performance
As Google recommends, one should avoid multiple calls to getValues / setValues and such, instead grabbing all necessary data at once, processing it, and making batch changes at once. E.g., instead of placing it a row in another sheet, add it to an array; when the loop ends, place the entire array in that sheet.
I have following code to create a single pdf with 2 columns and 4 rows. Every cell contains an image.
int labelCount = x;
int columns = 2;
int labelsPerPage = 8;
int rows = labelCount/columns;
int resto = labelCount%columns;
if(resto>0) rows++;
String dest = "path_to_pdf_file";
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
doc.setMargins(0, 0, 0, 0);
Table table = new Table(UnitValue.createPercentArray(columns)).useAllAvailableWidth();
Integer iCount = 0;
for (int i = 1; i <= rows; i++) {
for (int y = 1; y <= columns; y++) {
if(iCount<labelCount) {
String fileName = "name_of_image";
Cell cell = new Cell();
cell.add(new com.itextpdf.layout.element.Image(ImageDataFactory.create("full_path_to_image")).setAutoScale(true));
cell.setBorder(Border.NO_BORDER);
table.addCell(cell);
iCount++;
if(iCount==labelsPerPage-1) {
doc.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
}
}
}
}
doc.add(table);
doc.close();
If number of labels is bigger than defined limit (8 per page), I want a new page to be created with the following labels.
In my code I used
doc.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
but it generate (I don't know why) a blank page at the beginning. In the second page there are labels.
Which is the right way to add a new page dynamically and put remaining content into it?
Thanks
Essentially in your code you add AreaBreak to the document before you add the table, that's why the blank page is inserted before the table. iText 7 does not allow you to insert page breaks within tables at this point.
To achieve the desired result you need to flush the existing table to the document before moving on to the next page, and create a new table for the next page. Essentially you will be adding a bunch of tables separated with AreaBreak.
The pseudocode which does not require a lot of modifications to your code could look as follows:
Table table = new Table();
for (...) {
// populate table
if ("it's time to insert a page break") {
doc.add(table);
doc.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
table = new Table(); // create new table
}
}
doc.add(table);
I can sort (descending) my displayed results by a selected value using this code:
PivotField field = pivotTable.RowFields[0];
field.IsAutoSort = true;
field.IsAscendSort = false;
field.AutoSortField = 1;
This is what I see (Total Purchases displayed are indeed shown from most to least):
Or, I can only display Description ranges whose "Percentage of Total" value is at least 1% with this code:
private void HideItemsWithFewerThan1PercentOfSales()
{
int FIRST_TOTAL_PRICE_ROW = 8;
int ROWS_BETWEEN_PERCENTAGES = 4;
var pivot = pivotTableSheet.PivotTables[0];
var dataBodyRange = pivot.DataBodyRange;
int currentRowBeingExamined = FIRST_TOTAL_PRICE_ROW;
int rowsUsed = dataBodyRange.EndRow;
pivot.RefreshData();
pivot.CalculateData();
// Get grand total of purchases for all items and months, and calculate what 1% of that is
Cell totalTotalPurchasesCell = pivotTableSheet.Cells[rowsUsed - 2, _grandTotalsColumnPivotTable + 1];
double totalTotalPurchases = Convert.ToDouble(totalTotalPurchasesCell.Value);
var onePercentOfTotalPurchases = totalTotalPurchases / 100;
// Loop through PivotTable data, hiding where percentage < 0.01 (1%)
while (currentRowBeingExamined < rowsUsed)
{
Cell priceCell = pivotTableSheet.Cells[currentRowBeingExamined, _grandTotalsColumnPivotTable + 1];
String priceStr = priceCell.Value.ToString();
Double price = Convert.ToDouble(priceStr);
if (price < onePercentOfTotalPurchases)
{
pivotTableSheet.Cells.HideRows(currentRowBeingExamined - 1, ROWS_BETWEEN_PERCENTAGES);
}
currentRowBeingExamined = currentRowBeingExamined + ROWS_BETWEEN_PERCENTAGES;
}
}
...like so:
...but I can't get them both to work at the same time. So I can either hide the Descriptions with less than 1% of the percntage OR I can sort by Total Purchases descending, but I'm not able to accomplish both at the same time. My code to try to accomplish both is as follows:
. . .
pivotTable.AddFieldToArea(PivotFieldType.Row, DESCRIPTION_COLUMN);
pivotTable.RowHeaderCaption = "Description";
// Dragging the second field to the column area.
pivotTable.AddFieldToArea(PivotFieldType.Column, MONTHYR_COLUMN);
pivotTable.ColumnHeaderCaption = "Months";
// Dragging the third field to the data area.
pivotTable.AddFieldToArea(PivotFieldType.Data, TOTALQTY_COLUMN);
pivotTable.DataFields[0].DisplayName = "Total Packages";
pivotTable.AddFieldToArea(PivotFieldType.Data, TOTALPRICE_COLUMN);
pivotTable.DataFields[1].DisplayName = "Total Purchases";
. . .
// Sort by "Total Purchases" descending
PivotField field = pivotTable.RowFields[0];
field.IsAutoSort = true;
field.IsAscendSort = false;
field.AutoSortField = 1; // This is the "Total Purchases" field
pivotTable.PivotTableStyleType = PivotTableStyleType.PivotTableStyleLight16;
pivotTable.RefreshDataFlag = true;
pivotTable.RefreshData();
pivotTable.CalculateData();
pivotTable.RefreshDataFlag = false;
List<String> contractItemDescs = GetContractItemDescriptions();
ColorizeContractItemBlocks(contractItemDescs);
HideItemsWithFewerThan1PercentOfSales();
FreezePanePivotTable(HEADER_ROW, 2);
FormatPivotTableNumbers();
ConfigureForPrinting(pivotTableSheet.Cells.Rows.Count);
It's as if the sorting order is not being respected when HideItemsWithFewerThan1PercentOfSales() is called - the row numbers that method "sees" is not the row numbers according to the sorting that has been established.
How can I get both the sorting AND the hiding to work?
NOTE: Calling HideItemsWithFewerThan1PercentOfSales(); prior to the sorting code does NOT work - it still shows/hides some of the wrong things.
Please check the reply in this thread in Aspose.Cells forum.
Note: I am working as Developer Evangelist at Aspose
I'm trying to create a drop down menu with contents based on a another cell in the same row. For example if A1 = 'yes' then the drop down in B2 gives you the options of 'yes' or 'no'. I can do this I have the list data set up and to code works. The problem is I need to do this 155 times in 4 different sheets. Is there a faster way to do this than right clicking and editing the data validation rules for each cell. Here's a link to the test sheet I'm working on :
https://docs.google.com/spreadsheets/d/1rd_Ig_wpof9R_L0IiA1aZ9syO7BWxb6jvBhPqG8Jmm4/edit?usp=sharing
You can set data validation rules with a script, as documented here. Here's a reference for starting with Apps scripts.
I wrote a function that does approximately what you described. It works with the range B3:B157 of the sheet '9th grade' in the current spreadsheet. For each of them, it sets the validation rule to be: a value in the same row, columns B and C of sheet 'List Data'. The line with
....... = listData.getRange(i+3, 2, 1, 2);
will need to be modified if the source range of validation is to be different. Here, the parameters are: starting row, starting column, number of rows, number of columns. So, 2 columns starting with the second, in row numbered i+3.
function setRules() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var grade = ss.getSheetByName('9th Grade');
var listData = ss.getSheetByName('List Data');
var range = grade.getRange('B3:B157');
var rules = range.getDataValidations();
for (var i = 0; i < rules.length; i++) {
var sourceRange = listData.getRange(i+3, 2, 1, 2);
rules[i][0] = SpreadsheetApp.newDataValidation().requireValueInRange(sourceRange).build();
}
range.setDataValidations(rules);
}
I land in this issue for a diferent reason: "Just mass DataValidation copy (or update) in one column". Thanks, to user3717023 that bring me a light.
I hope that helps someone this simplification.
function setRules() {
//select spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var leads = ss.getSheetByName('Leads');
//Select correct Datavalidation
var rangeNewDataValidation = leads.getRange('M2:M2');
var rule = rangeNewDataValidation.getDataValidations();
//Copy (or Update) Datavalidation in a specific (13 or 'M') column
var newRule = rule[0][0].copy();
Logger.log(leads.getMaxRows())
for( var i=3; i <= leads.getMaxRows(); i++){
var range = leads.getRange(i, 13);
range.setDataValidations([[newRule.build()]]);
}
}
I am working on a UI. My job is to automate it. I came across the following grid.
When you click on any cell under the Rule column, a browse button appears.
I am supposed to automate this scenario. So, using Firebug I am trying to extract the XPath of that cell.
I used Firebug's inspector to locate that particular cell, so that I can write the XPath for it, but I am unable to locate that cell. Instead, the entire row is getting selected, as shown in next images.
How should I approach this problem?
below code might help you to verify the grid values,
public void verifyTableValues(String expectedValue
) {
try {
//List of Fields values which you want to verify
List<String> expectedValues = Arrays.asList(expectedValue.split("#"));
// you will get the number of rows in Table Select the xpath to /tr
String tableRow = driver.findElements(By.xpath(//table row constant));
int tableRwCnt = getCount(tableRow);
// you will get the number of Columns in Table Select the xpath to /td
String tableColumn = driver.findElements(By.xpath(//table Column constant));
int tableColumnCnt = getCount(tableColumn);
for (int cnt = 1; cnt <= tableRwCnt; cnt++) {
for (int listCount = 1; listCount <= tableColumnCnt; listCount++) {
String actualVal = findElement(By.xpath(tableColumn + "[" + cnt + "]/td["
+ expectedValues.get(listCount) + "]").getText();
String expectdVal = expectedValues.get(listCount);
Assert.assertEquals("Value from table doent Match", expectdVal, actualVal);
}
}
} catch (Exception e) {
// code for exception
}
}
Parameter: expectedValue = test1#test2#test4#test4 (Grid values)