I want to create two tables side by side in flow document.
I don't want to use blockuicontainer.
It is all composition, you need to put the two tables inside another table which has the dimensions of one row with two columns, something like this:
Table table1 = CreateTable1();
Table table2 = CreateTable2();
var containingTable = new Table();
var containingRowGroup = new TableRowGroup();
var containingColumn1 = new TableColumn();
var containingColumn2 = new TableColumn();
containingTable.Columns.Add(containingColumn1);
containingTable.Columns.Add(containingColumn2);
containingTable.RowGroups.Add(containingRowGroup);
var containingCell1 = new TableCell();
var containingCell2 = new TableCell();
containingCell1.Blocks.Add(new Section(table));
containingCell2.Blocks.Add(new Section(table2));
var containingRow = new TableRow();
containingRow.Cells.Add(containingCell1);
containingRow.Cells.Add(containingCell2);
containingRowGroup.Rows.Add(containingRow);
document.Blocks.Add(new Section(containingTable));
Related
I would like to compare multiple values in a Google Sheet spreadsheet some using for loops in Google App Script. But i would like some advice on the best way to do it.
To explain below...
I have two spreadsheets, A "FOOD" table, and A "FOOD GROUP" table.
I've written a for loop script that goes through the entire FOOD table.
If the key value of both tables matches, the script will update a column from the FOOD table with a column from the FOOD GROUP table.
The script works without issues. But it can only compare one column between the 2 tables at a time. I would like to modify this script so I can compare multiple columns at once, without having to create a for loop for each specified column.
I pasted my code below. I can also provide images of my spreadsheet if you need it.
In any case, I'm new to coding, so any constructive feedback or insight to improve my script will be helpful. I'm happy to answer any questions if anything seems unclear.
function FoodGroup_Test() {
var Data = SpreadsheetApp.getActiveSpreadsheet();
var FoodGroupDataSheet = Data.getSheetByName("Food Groups") // "FoodGroup" sheet
var FoodGroupAllValues = FoodGroupDataSheet.getRange(2, 1, FoodGroupDataSheet.getLastRow()-1,FoodGroupDataSheet.getLastColumn()).getValues();
var FoodGroupDataLastRow = FoodGroupDataSheet.getLastRow();
var FoodDataSheet = Data.getSheetByName("Food") // "Food" sheet
var FoodAllValues = FoodDataSheet.getRange(2, 1, FoodDataSheet.getLastRow()-1,FoodDataSheet.getLastColumn()).getValues();
// Object to contain all FoodGroup column values
var Object = {};
for(var FO = FoodGroupAllValues.length-1;FO>=0;FO--) // for each row in the "FoodGroup" sheet...
{
Object[FoodGroupAllValues[FO][15]] = FoodGroupAllValues[FO][11]; // ...store FoodGroup ID Key value
}
for(var F = FoodAllValues.length-1;F>=0;F--) // for each row in the "Food" sheet...
{
var Food_FoodGroupKey = FoodAllValues[F][94]; // Store FoodGroup Key value.
// ...if the Food value dont match, update it with FoodGroup's value
if (Object[Food_FoodGroupKey] != FoodAllValues[F][95])
{
FoodAllValues[F][95] = Object[Food_FoodGroupKey];
}
}
// declare range to place updated values, then set it.
var FoodDestinationRange = FoodDataSheet.getRange(2, 1, FoodAllValues.length, FoodAllValues[0].length);
FoodDestinationRange.setValues(FoodAllValues);
}
FOOD GROUP Table
FOOD table
In order for your code to work as expected, you should do the following changes to your code:
Update your if condition to this one:
Object[Food_FoodGroupKey] != FoodAllValues[F][95] && object2[] != FAllValues[F][86])
In order to avoid the undefined problem use the following line of code:
FoodDataSheet.createTextFinder("undefined").replaceAllWith("");
I'm new to JavaScript... I have 2 spreadsheets created. 1 that has input values, and the 2nd is a target sheet where I want to update information.
I am searching through the target sheet with values from the input sheet with a column labeled "OpportunityID". Once the associated row is found, I want to update the target row with the values from the input sheet.
I've been able to search the target sheet with OpportunityID value from the input sheet and pull the values of columns in that specific row, but I am having trouble changing the values on the target sheet to the corresponding values on the input sheet.
Here is the code I have tried so far that pulls the appropriate information, but I need help resetting the values of that row:
function updateOpportunity() {
// Get active spreadsheets and sheets
var inputSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Search & Create New Records');
var OppsAndContracts = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Opportunities & Contracts');
var opportunityUpdateCopy = inputSheet.getRange('A8:Q8').getValues();
Logger.log(opportunityUpdateCopy);
//Search for Opportunities using OpportunityID
var last=OppsAndContracts.getLastRow();
var data=OppsAndContracts.getRange(1,1,last,17).getValues();// create an array of data from columns A through Q
var opportunityID = updateSheet.getRange("A8").getValue();
Logger.log(opportunityID);
for(nn=0;nn<data.length;++nn){
if (data[nn][0]==opportunityID){
var OppID = (((data[nn][0])));
var OppName = ((data[nn][1]));
var AccountID = ((data[nn][2]));
var AccountName = ((data[nn][3]));
var OppOwner = ((data[nn][4]));
var CloseDate = ((data[nn][5]));
var Amount = ((data[nn][6]));
var ProposalOwner = ((data[nn][7]));
var Stage = ((data[nn][8]));
var AeroServicesProducts = ((data[nn][9]));
var MechServicesProducts = ((data[nn][10]));
var ProjectStatus = ((data[nn][11]));
var PaymentIssues = ((data[nn][12]));
var UniquePaymentTerms = ((data[nn][13]));
var PaymentTerms = ((data[nn][14]));
var ProposalNumber = ((data[nn][15]));
var ContractNumber = ((data[nn][16]));} ;
OppsAndContracts.getRange([data]).setValues(opportunityUpdateCopy);
}
I've also tried getting the cell reference of the cells in the row with the corresponding OpportunityID and setting them with the values from the input sheet, but that hasn't worked either.
Any help or advice is much appreciated!
You need to use the nn value to select the range when there's a match, since nn is effectively your row index.
function updateOpportunity() {
// Get active spreadsheets and sheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var updateSheet = ss.getSheetByName("Update Sheet"); // You didn't have this defined, so I added
var inputSheet = ss.getSheetByName('Search & Create New Records');
var OppsAndContracts = ss.getSheetByName('Opportunities & Contracts');
var opportunityUpdateCopy = inputSheet.getRange('A8:Q8').getValues();
//Search for Opportunities using OpportunityID
var last = OppsAndContracts.getLastRow();
var data = OppsAndContracts.getRange(1,1,last,17).getValues(); // create an array of data from columns A through Q
var opportunityID = updateSheet.getRange("A8").getValue();
for (var nn = 0; nn < data.length; ++nn) {
if (data[nn][0] == opportunityID) {
OppsAndContracts.getRange(nn + 1, 1, 1, 17).setValues(opportunityUpdateCopy);
}
}
}
(I removed a bunch of the code that was irrelevant to your question.)
I'm trying to solve this question but despite the effort I have not advanced!
Every day I get a spreadsheet with two tabs of data. Each one has about 9 thousand rows. I need to capture the data from this worksheet and generate two new spreadsheets with one for "daily reporting" (with only the data of this day) and another for create a "database" (with all data previous results). How can I do this automatically with GAS?
I working in this code below so far, but when I will set the values in the new spreadsheet, I got error about range. :( I don't know how to declare that I want copy and set all the rows between 10 and the last with data from
function getData() {
var day = SpreadsheetApp.openById('XXXX');
var tab1 = day.getSheets()[0];
var tab2 = day.getSheets()[1];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sss = ss.getSheets()[0];
var weeks = tab1.getRange("G8").getValues();
var dates = tab1.getRange("G9").getValues();
var regions = tab1.getRange('A10:A').getValues();
var locnames = tab1.getRange('B10:B').getValues();
var locnums = tab1.getRange('C10:C').getValues();
var divisions = tab1.getRange('D10:D').getValues();
var depnums = tab1.getRange('E10:E').getValues();
var depnames = tab1.getRange('F10:F').getValues();
var saless = tab1.getRange('G10:G').getValues();
var qtys = tab2.getRange('G10:G').getValues();
var datestart = sss.getRange('A2').setValues(dates);
var dateend = sss.getRange('B2').setValues(dates);
var week = sss.getRange('C2').setValues(weeks);
var region = sss.getRange('D2:D').setValues(regions);
var locname = sss.getRange('E2:E').setValues(locnames);
var locnum = sss.getRange('F2:F').setValues(locnums);
var division = sss.getRange('G2:G').setValues(divisions);
var depnum = sss.getRange('H10:H').setValues(depnums);
var depname = sss.getRange('I2:I').setValues(depnames);
var sales = sss.getRange('J2:J').setValues(saless);
var qty = sss.getRange('K2:K').setValues(qtys);
}
If anyone can help me, thank you immensely.
I put a spreadsheet in the link to illustrate the format of sheets and what I need to do. The first two tabs are the same as the ones I get. And in the next two tabs(daily_report, database) are the worksheets that I want to get separately with the code.
https://docs.google.com/spreadsheets/d/1_iz0oansAfINosV2qNoDG0QMNpGS1bp1AL5kJQztRtc/edit?usp=sharing
The target range must be matched to the source range, or there will be an error. The length and width of the target range must be the same as the source data. You can use the data to set the length (number of rows) and width (number of columns)
Parameters:
range(Start Row, Start Column, Number of Rows, Number of Columns)
Code:
var regions = tab1.getRange('A10:A').getValues();
var region = sss.getRange(2,4,regions.length,regions[0].length).setValues(regions);
I was trying to use the Where and OrWhere methods of SqlBuilder for Dapper, but it is not acting like how I would expect.
The edited portion of this question is basically what I ran into. Since it didn't receive a response, I'll ask it here.
var builder = new SqlBuilder();
var sql = builder.AddTemplate("select * from table /**where**/ ");
builder.Where("a = #a", new { a = 1 })
.OrWhere("b = #b", new { b = 2 });
I expected select * from table WHERE a = #a OR b = #b
but I got select * from table WHERE a = #a AND b = #b
Is there any way to add an OR to the where clause using the SqlBuilder?
I think it's just a matter of changing the following in the SqlBuilder class to say OR instead of AND, but I wanted to confirm.
public SqlBuilder OrWhere(string sql, dynamic parameters = null)
{
AddClause("where", sql, parameters, " AND ", prefix: "WHERE ", postfix: "\n", IsInclusive: true);
return this;
}
Nevermind. I looked through the SqlBuilder code and found that if there is a mixture of Where and OrWhere, it will do the following:
Join all the AND clauses
Join all the OR clauses separately
Attach the OR clauses at the end of the AND clauses with an AND
If you don't have more than 1 OrWhere, then you won't see any OR.
I'll modify my query logic to take this into account
You have to change your query into:
var builder = new SqlBuilder();
var sql = builder.AddTemplate("select * from table /**where**/ ");
builder.OrWhere("a = #a", new { a = 1 })
.OrWhere("b = #b", new { b = 2 });
In case you want to try another alternative, DapperQueryBuilder may be easier to understand:
var query = cn.QueryBuilder($#"
SELECT *
FROM table
/**where**/
");
// by default multiple filters are combined with AND
query.FiltersType = Filters.FiltersType.OR;
int a = 1;
int b = 2;
query.Where($"a = {a}");
query.Where($"b = {b}");
var results = query.Query<YourPOCO>();
The output is fully parametrized SQL (WHERE a = #p0 OR b = #p1).
You don't have to manually manage the dictionary of parameters.
Disclaimer: I'm one of the authors of this library
I have seen QueryMultiple from Dapper official doc as below, It is convenient!
var sql = #"
select * from Customers where CustomerId = #id
select * from Orders where CustomerId = #id
select * from Returns where CustomerId = #id";
using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
...
}
Now, when I delete record from Parent-table,I want to delete related record from Child-table.
can Dapper fit it? It looks that as below.
var sql = #"delete from tb_role where roleid=#ID
delete from tb_rolepermission where roleid=#ID
delete from tb_userrole where roleid=#ID
";
var param = new { ID=id };
connection.EXECUTEMultiple(sql, param)..........
Any help will be appreciated!
Yes, you can can simply call connection.Execute and it already allows multiple commands like you are trying to do, the same as ExecuteQuery allows on SqlCommand, which is all Dapper is calling anyways.