Reading barcode in datawindow (powerbuilder) - barcode

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.

Related

Google sheets api adding multiple rows

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.

The operation TimerInterval cannot accept the arguments: [(1800)] in App Inventor 2

I'm stuck on an error in my App Inventor 2 application. I' m using three checkboxes, so the user to pass values to a timer interval in a clock component.
The values are stored in a variable as a list of three values of miliseconds (e.g. 1600, 1800, 2000). I check in code when and which checkbox is checked and then pass it over to a TinyDB database as a tag.
Problem is that, in Do it and on the device running the app, I get the following error as title suggests.
Here is the coding blocks I've used so far:
Does anyone be kind enough to direct me to how solving this error? Is it possible to pass values to a clock component through this logic. I've used a listPicker with success sometime ago, but I need it done with a checkBoxes layout. Thank you all in advance for your answers.
[Edit1]
To overcome this error and before #Taifun's remarks and suggestions, I followed the variable path, to pass values in the timer interval field. Do not now if it is very efficient but it is working for now. Here is the coding blocks:
Bracket pairs like this () represent a list.
The operation TimerInterval cannot accept the arguments: [(1800)]
This is, what the error message is trying to tell you: You are trying to assign a list, which has the item 1800 inside, to the TimerInterval property of a clock component.
You should assign the value directly instead.
Also you should think about the default value: which value should be used, if the user did not store anything in TinyDB... You are currently using an empty string in the valueIfTagNotThere socket... This does not really make sense... A better value would be for example 1000 ... same for the else part in your if-then-else statement...

App Inventor TinyWebDB List Problems

I got a problem using the TinyWebDB in App Inventor 2. Here's a Screenshot of the blockcode.
The goal of this Screen is to store a list(array) of images and later query them with a button but my problem starts already earlier. First there is a variable initialized called fotoList and declared as an empty list.
When this Screen initializes (left block) I store the empty fotoList under the tag FotoListTag. Then if the image under the tag "SteckbriefFoto" is not in this list -> getValue with tag "FotoListTag". Then he jumps into the block on the right and adds the photo .. other stuff not important .. at the end I store the list again in the TinyWebDB (and also in the TinyDB) with the tag "FotoListTag". Then it goes back to the block on the left where at the end I want to set an image.picture to the photo I stored in variable fotoList.
When I compile the code there is an error opening the page that says
Select list item: List index too large
Select list item: Attempt to get item number 1 of a list of length 0:()
I just don't get the problem with this code and i hope someone can help me.
For lists, valueIfTagNotThere should be create empty list instead of an empty string
On first run of your app, TinyDB is empty, which means, for tag = FotoListTag you get no value back, therefore this should be an empty list in the beginning.
Later you are trying to select the first item from the list (zahl is 1). As you know, the list is empty in the beginning, so probably you should add an if statement to check, if the list is not empty and only then select the first item... same for tag = Schriftlist.
You also have a timing issue. in Screen.Initialize you are trying to get a value from TinyWebDB. This is an asynchronous call, you get the result back in TinyWebDB.GotResult event and this takes a little bit (let's say 500 milliseconds), but meanwhile the complete blocks of the Screen.Initialize event will be executed. Probably you are expecting, that meanwhile tag = FotolistTag is not empty anymore, but this is not the case.

Character length in single line edit filter PowerBuilder

My SQL code gives me over 10 000 rows, each containing client id, name, address and so forth. In my PowerBuilder 10.5 window I've set my DataWindow in which I'm retrieving my SQL code using id as retrieve argument. I have a Single line Edit (sle_id) in which the user can write an id and search by it. What I've figured out is that all of my clients have id's length of 8 characters and starting with either "46XXXXXXXX" or "7052XXXX". So to optimize my retrieve time I want to write a code in the clicked event of my "Start" button that is located in PowerBuilder window that would first check if the id starts with one of does two options: "46..." or "7052...". I assume I'd need to use length of the characters? For example, this is what I'd want...
IF sle_id.text STARTS with 46 or 7052 THEN retrieve
ELSE MessageBox ("INFO", "Your id must have begin with either 32 or 7052")
END IF;
Of course, I need something better then "Starts with". Much oblige for all the help!
there are some string functions in powerbuilder. I think you need this:
If( left(sle_id.text, 2) = "46" or left(sle_id.text, 4) = "7052" ) then
Best Regards
Gábor
I think you're trying to solve the wrong problem. Your database should have an index on client id. If the client id is unique use a unique index.

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