Google sheets api adding multiple rows - google-api

I'm trying to figure this out and I must be overlooking something basic. (It took me WAAAY longer than it should have just to realize I hadn't added the trigger.)
When forms are submitted, if that page runs out of rows, it automatically expands. I have a reconciliation page where it is pulling the submitted data over line by line and analyzing it for discrepancies (the form collects billable time and tasks.)
So while the Form Responses 1 page will expand, I want to use a trigger on form submit to add a line to the reconciliation page and copy the formulas down. I can't seem to get the line to add though. Looking at the google page for expanding the number of rows, I'm not sure what I am doing wrong there either but I THINK I need to add more java features to my computer.
If I simply copy and paste the example into a new sheet, most of the code is black instead of the standard editor colors. Saving pops up "Missing ; before statement. (line 1, file "Code")"
Line one is simply "import com.google.gdata.client.spreadsheet.*;"
So zerothly: Whats the most basic code I can use to add that blank row?
Then first: Do I need to import a bunch of stuff to get this (adding rows) to work?
Second: If so, and I transfer ownership of the sheet to someone, do they need to do the imports also?
Third: If so, and I want to do edits on another device, will I need to do imports there too?
Fourth: The example uses Update() but I can't seem to find an Update() function in javascript or googlesheets api documentation.
This is the code I am trying and variations commented out which doesn't seem to work:
function onFormSubmit(e) {
Logger.log('form submit triggered')
var sheet = SpreadsheetApp.getActive()
var sss = sheet.getSheetByName('Reconciliation')
var col2 = sss.getRange("B:B");
var col2val = col2.getValues();
var counter = 0;
var sssrange = sss.getDataRange();
// sss.Rows = sss.getLastRow() + 1 //Object does not allow properties to be added or changed if I uncomment - this seems to match the google example line though
Logger.log(sss.getLastRow());//=8
var newsssrange = sssrange.offset(1,0); // didn't actually think this would work (since it also had the .update() part that previously didn't work for me) but came across it and was getting desparate.
// sss.setRowCount(sss.getLastRow() + 1); // TypeError: Cannot find function setRowCount in object Sheet.
Logger.log(sss.getLastRow()); //=8
// sss.Update();//TypeError: Cannot find function Update in object Sheet.
}

Sigh... I am still wondering how to add more rows but I did answer my original need of adding a single line since form submits only add a single line. So I'm going to answer it since I had done so many searches and for some reason this never came up, maybe someone will find this useful if they are having the same issue.
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActive()
var sss = sheet.getSheetByName('Reconciliation')
sss.appendRow(['']);
}
Note that this adds a single blank line. If you run it a second time it won't add a second blank line as appendRow() adds after the last line with data. If you put a string in there or something and run it over and over you will get multiple lines.
I really would like to know about adding multiple lines though also since that will come up and I still seem to be missing something, probably obvious.

Did you know that arrayformula woluld make new lines automatically.? If you paste this formula in Sheet2:
=OFFSET(Sheet1!A1,,,counta(Sheet1!A:A))
and then paste new values in Sheet1 range A:A, then new rows would be added on Sheet2.

Related

Reading barcode in datawindow (powerbuilder)

I have like a POS application where I work, and I added new code to read barcodes in a datawindow, but been having some problems to use it correctly. The process needs to read the barcode and automatically search for the product, and insert it in another datawindow with the info regarding the product.
The problem is that I have the code in the editchanged event, and that the barcodes have different lenght; so, every time a number of the barcode is read, the search function is called, here is the code for that function:
ll_rtn = dw_search.Retrieve()
If ll_rtn = 1 Then
is_code = dw_search.GetItemString(1,'barcode')
wf_insert(False)
End If
If for example, a product of 10 digits is read and at length 5 the product is found, it's inserted but the editchanged is still running because the barcode is length 10, and depends of the search, might find it again with the last digits and insert it again.
I don't know how to stop reading after I find the product. Hope I explain it right.
Can you check if the barcode scanner can be configured to pass carriage return / Enter, upon scanning the barcode and this way you can move your code to itemchanged event
Bar Code Config
An editchanged event is fired for each keystroke in the control. You probably want to either move the code to the itemchanged event or to a totally separate event which is posted from the itemchanged event.
If you absolutely have to have the code in the editchanged event you need to set a boolean instance variable on the window which is set TRUE once the product is found. If it's true then don't search. Remember to reset the variable to FALSE prior to any new search.

Importing flat file into SSIS gives problems because non-consistent deliminater

I am facing a problem importing a flat file into SSIS.
The file is seperated by "|" and has deliminater as ";;". However the deliminator is inconsistent. Sometimes, at the and of the rows, there is only ";" or nothing "". When importing to SSIS I get the result
Column 1 Column 2 Column 3 Column 4 Column 5
a b c d e;|a1|b1|c1|d1|e1
This should instead look like
Column 1 Column 2 Column 3 Column 4 Column 5
a b c d e
a1 b1 c1 d1 e1
And the problem arrises because in the first row there is only one or none ";".
Note this is an example, many of the rows are correct and have ";;" as deliminator. I am only pointing out the problem.
The .csv file would look like
Column 1|Column 2|Column 3|Column 4|Column 5;;
a|b|c|d|e;
a1|b1|c1|d1|e1;;
and should instead look like
Column 1|Column 2|Column 3|Column 4|Column 5;;
a|b|c|d|e;;
a1|b1|c1|d1|e1;;
The data set is very big with almost 600.000 rows and 50 columns.
The first problem I face is when I import the file, since SSIS standard DataType reading is string [DT_STR]. with a length of 50. Since sometimes there are multiple rows with wrong deliminators, I get a very long strings in the last column cell. I Use Visual Studio, and in the Advanced Editor I changed the length to something very big.
Advanced editor in Visual studio were I have changed the length
So the question is, how do I in SSIS and Visual Studio Community separate the values in some cells in one column and split op these into a entire new row (with the already defined column variables).
I have tried manually to find all the cases where there is a error and changed this in the .csv file. After this SSIS works. However this is not a durable solution because I am getting a new file every month.
I have tried reading suggestions as:
Split a single column of data with comma delimiters into multiple columns in SSIS
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/49a764e7-1a6f-4a6f-9c92-2462ffa3add2/regarding-ssis-split-multi-value-column-into-multiple-records?forum=sqlintegrationservices
but their problem is not he same, since they have a column value the replicate, and I want a entire new row.
Thanks for any help,
ss
!! EDIT trying using the answers from J Weezy and R M: !!
I try to create a script task and follow that solution.
In Visual Studio, I add a script task using a Script Component and I choose "Transformation". Under Input Columns I choose all.
After this i direct the flat file source to the script component and run the code. Running the script like this (where the script component doesn't do anything) works.
Then I enter "Edit Script" in the script component, and under public override void Input0_ProcessInputRow(Input0Buffer Row) I enter (using the help from R M):
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
public static string[] SplitLine(string input)
{
Regex lineSplit = new Regex("[0-9]\;$", RegexOptions.Compiled);
List<string> list = new List<string>();
string curr = null;
foreach (Match match in lineSplit.Matches(input))
{
curr = match.Value;
if (0 == curr.Length)
{
list.Add("");
}
list.Add(curr.TrimStart(';'));
}
return list.ToArray();
}
}
However this doesn't work (I am not even allowed to execute the task).
I have never worked with c# before so everything is new to me. As i understand the code, it search each line to find the pattern where there is numbers in front of only one ";" at the end, hence it will not find those lines which ends with numbers following by ";;" (two ;).
When there is a match, one ";" is added.
Please let me know, what I am not understanding and doing wrong.
Maybe it is also wrong to put the script component after the flat file source, because adding ";" will not result in a new line, which is what I want.
Inconsistent row delimiters is bad data and there really is no way to correct for this in either the connection manager or the data flow. Fixing bad data within the data flow is not what SSIS was designed for. Your best bet is to do one of the two following:
Work with the data source provider to fix the issue on their end
Create a script task to first modify the file to correct the bad data
From there, you will be able to process the file normally in SSIS.
Update 1:
If the only problem is a duplicate delimiter (;;), then read in the row and use the Replace(";;",";"); function. If you have either multiple duplicate or invalid end of row delimiters, then you are better served by using StringBuilder(). For a solution on using StringBuilder(), see the weblink below.
https://stackoverflow.com/a/49949787/4630376
Update 2:
One thing that I just remembered, you will need to adjust for handling only those characters that are outside of double quotes, assuming that double quotes exist within the file as the text qualifier. This is important because without it you will remove any characters that are within quotes, which may be valid data.
I would agree with J Weezy to create a script task to correct the bad data. In the script task you could possibly use regex to deal with the “;” and “;;” issue. The script task may be your only way of dealing with the the “;” and “;;” issue.
While the below code in its current form will not work for your case, it possibly could be changed to work for your case. I have used it to deal with processing a text\csv file to correct formatting issues with each line of data. Note I got this from another post on Stackoverflow.
public static string[] SplitLine(string input)
{
Regex lineSplit = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)", RegexOptions.Compiled);
List<string> list = new List<string>();
string curr = null;
foreach (Match match in lineSplit.Matches(input))
{
curr = match.Value;
if (0 == curr.Length)
{
list.Add("");
}
list.Add(curr.TrimStart(','));
}
return list.ToArray();
}

Pentaho: How to rollup time

I have time for example I have in records time written in this way: 00:02:24 or 15:22:45, and now I want to make another column (hours), where can be values for example for time 02:43:22 is value 2, or for time 23:22:14, is value 23 and so on. But I don't know how can I do that, I tried number range, but unsuccessfully.
Here is a picture, how i want to be:
Thanks.
You can use the Modified JavaScript Value step.
I do not know which type is your Time.
If it is a String, a var Hour = Time.substr(0,2); will do.
If it is a Date, use var Hour = Time.getHour();.
If the type is something else, then convert in a String first.
To do this:
drag-and.drop the step Modified JavaScript Valueand link it to the data flow provider (in the example a Data grid).
edit this step and add your script. (Note that you can quickly add the input variable with a double click. Note also that clicking on the Transformation Function in the left menu gives you the list of available function additional to the Javascript built-in collection).
Click on the Get variable button, keep the variable you need (here Hour), and define/redefine its type (here String).
That's done: OK and preview.
If needed, adapt to the type of your input flow. For example Hour = Hour+'' to force a type conversion into a String.

BIRT Repeating only part of a header

What I am currently trying to do in BIRT 4.5 is repeat only a specific part of my tables header. However when I set it to repeat the header it always repeats the entire header.
Is there a way to only repeat a specific part of the header?
In my example - there is two headers, the "table name" and the "column headings". I only want the column headings to repeat. I have a feeling its likely going to be a scripted fix, but have no idea where to go to start it.
this might get tricky because headers can be repeated for groups but also for pagebreaks.
Not the most fancy, but you should get something working by defining a global variable on the page script
var headerCount = 0;
Then select an element in the header, open the onPrepare script and have it increment the counter:
headerCount = headerCount + 1;
with this information, you can make true/false statements in the visibility property.
Each object has onPrepare, onCreate, onRender and onPagebreak scripts. Not sure what the exact difference, so you have to experiment a bit with this. (because when an element should increase the counter, but is not rendered due to the visibility clause, you can get unexpected results.)
Good luck!

print line before page changed in vfp reports

I'm creating a report in vfp. The report contains grouping. In the end of each group, i draw a line. Each row in the detail band doesn't contain any line, only at the end of each group. The problem is when the group expand to the next page, in the previous page i want to draw a line at the bottom. Like this :
(page 1)
group A
name, etc
x1,etc
x2,etc
???how do I add line here?
(page 2)
group A
name,etc
x3,etc
x4,etc
group B
name,etc
y1,etc
y2,etc
I've tried to place the line in the page footer band, but the last line of the report doesn't have exact position, so it doesn't look nice.
Hope I described the situation clear enough. Thank You for taking the time to help me.
Without some significant smoke-and-mirrors trickery: running the report twice, once hidden and track where the breaks are via function calls in the report, and then again for production, its not EASILY done.
The only thing I could suggest is putting a line at the TOP of a PAGE FOOTER which prints on EVERY page. How long have you been working with VFP. Depending, I MIGHT be able to guide you through it.
Ok, here are the steps I would take. This is under the assumption that you are pre-querying the results for your report and ordering them by some means into a temporary report cursor. You need to add 2 columns to your query as place-holders and be sure your do your cursor as " INTO CURSOR READWRITE " as we will be writing to this from within the report... that is the trick.
Next, modify your report. Go to the detail band and put a single line at the bottom of it. Adjust as needed if you need a few pixels under the last detail element. Double click the line and get to the tab where it allows you to put in a "Print When" condition for the line. Enter one of the new column names called "ShowLine" (but without the quotes).
Now, the "hook" for smoke and mirrors. Create another textbox field output in the report detail. It can be as small as 2 pixels wide and never actually prints anything. It can be put at the beginning or end of the report detail, no matter, just as long as its in the detail band. Double click it to bring up what it will print. In the expression, enter the following... WhatPageAmIOn( _PageNo )
This will actually call a function we'll add to your program which writes back to your report cursor... I'll hit that next.
Now, the code. The following is a sample snippet of code I've written to query the data for the report, have the extra columns, and put into a READWRITE cursor. From that, I run the report but to NOCONSOLE so it doesn't actually visually do anything, just runs in the background. It then cycles through and looks for the break between each page and goes backward 1 record from the break and stamps that record as "ShowLine" = .T... Then run the report again as normal and you have your one line appearing in the detail band regardless of a data group, but always the last data line at the end of each page.
Here's the code
*/ Query your data, order by whatever,
*/ but tack on the two extra fields and make it READWRITE
select;
YourData,;
AnotherField,;
MoreData,;
.f. as ShowLine,;
00000 as WhatPage;
FROM ;
YourData;
ORDER BY ;
WhateverForYourReport
INTO ;
CURSOR C_RptData READWRITE
*/ Pre-run the report NOCONSOLE so your windows don't get messed up / scrolled
REPORT FORM YourReport NOCONSOLE
*/ now, go back to the cursor that your report ran with
SELECT C_RptData
*/ set a variable for the first page you are looking to find a break for.
*/ in this case, the first detail that APPEARED on page 2.
lnLastPage = 2
*/ Start at top of the report cursor file and keep going until we reach
*/ the end of file where the LOCATE can no longer find "Pages".
GO TOP
DO WHILE NOT EOF()
*/ find the first record on ex: Page 2
LOCATE FOR WhatPage = lnLastPage
*/ Did we find one?
IF FOUND()
*/ Yes, go backwards 1 record
SKIP -1
*/ This is the last detail that appeared on the page before it (ie: pg 1)
*/ Mark this line as ok to "ShowLine" the next time the report is run.
replace ShowLine WITH .T.
*/ Now, advance the page counter to look for the NEXT page break...
*/ ex: between page 2&3, 3&4, 4&5, etc...
lnLastPage = lnLastPage +1
ENDIF
ENDDO
*/ Run your final version of the report
REPORT FORM YourReport Preview (or print)
RETURN
Here's the only hook below to track/update the page associated with the detail. I don't know if you have a main "SET PROCEDURE TO" file, or just a bunch of free .PRG files all in your project, or even if your reporting is done from within a PRG file itself. however, all you need is this function to be included in any of those locations. For simplest test, I would just create it as a stand-alone .prg file (if you are NOT using SET PROCEDURE, or doing your report within a PRG file and not from within a class method/event).
FUNCTION WhatPageAmIOn
LPARAMETERS lnPage
replace whatPage WITH lnPage
RETURN ""
As in the original description, the report is going to include a field in the detail band based on a function "WhatPageamIOn" and passes the parameter of _PageNo which is the internal VFP variable that keeps track of the current report page that is typically used in report header / footers. So, as each detail is getting processed, we are "STAMPING" the detail data with whatever the page is. We return an empty string "" so nothing actually gets printed, yet we've hooked what we needed. From this, the loop finding the first record at the beginning of every page (starting at page 2), and skipping backwards to the last entry for the prior page and we're done.
Good luck.

Resources