how to code the itemchanged event and datawindows - events

I am using PowerBuilder classic 12.5
am having difficulties in inserting, editing, creating and printing reports.
i have a datawindow, dw_NewEmployee with dataobject, d_newrecord which is update-able.
should i use the columns to insert records through the columns or i
create single line texts on the window object
is the itemchanged event used on columns and rows on dataobject or
on single line texts... I am having trouble figuring out how to implement validation rules.
please give me an example to validate employee ID_Number

I see that you seem confused about the datawindow usage.
Let's try to summarize:
you create a new datawindow d_newrecord (say it is a grid) based on a sql select in your database, say select id_number, name from employee.
in the detail zone of the datawindow (that will be repeated for each record at runtime but that is only once in design), you need to put one column object for each column (here you will have id_number and name) these objects are both to display existing data and receive user input for editing data and inserting new records.
don't forget to set the Rows / Update properties if you need to make the dw updatable.
in the header zone of the datawindow you can have a static text associated to each column that is just here to display the column name, it does not concern table data.
in some window object, you place a datawindow control dw_newemployee where the content of the datawindow will be painted, you set d_newrecord as its dataobject.
you need to set at some point the transaction object of the dw, for example in the open() event of the window:
dw_newemployee.SetTransObject(sqlca)
dw_newemployee.Retreive() //if you are using some retreival arguments, don't forget to include them here
When you want to insert new data in your table (for example with a window button "add"), in the clicked() event of the button you call dw_newemployee.InsertRow(0) to insert at the end.
The ItemChanged() event will be triggered after one cell will be modified, you will be given the row, item (a dwobject) and new data. By choosing the returned value of the event, you can accept or reject the new data.
Here is an example for a field validation in itemchanged() event:
long ll_return_code = 0
string ls_column
ls_column = lower(dwo.name)
choose case ls_column
case "id_number"
if long(data) = 42 THEN
messagebox("validation error", "You cannot use 42 for the ID")
ll_return_code = 1 //reject and stay in cell
end if
case "name"
if data = "foobar" then
messagebox("validation error", "Do not use dummy value...")
ll_return_code = 2 //reject but allow to go elsewhere
end if
end choose
return ll_return_code

Related

How to use DWitemstatus in Power Builder

I'm learning about Power Builder, and i don't know how to use these, (DWitemstatus, getnextmodified, modifiedcount, getitemstatus, NotModified!, DataModified!, New!, NewModified!)
please help me.
Thanks for read !
These relate to the status of rows in a datawindow. Generally the rows are retrieved from a database but this doesn't always have to be the case - data can be imported from a text file, XML, JSON, etc. as well.
DWItemstatus - these values are constants and describe how the data would be changed in the database.
Values are:
NotModified! - data unchanged since retrieved
DataModified! - data in one or more columns has changed
New! - row is new but no values have been assigned
NewModifed! - row is new and at least one value has been assigned to a column.
So in terms of SQL, a row which is not modified would not generate any SQL to the DBMS. A DataModified row would typically generate an UPDATE statement. New and NewModifed would typically generate INSERT statements.
GetNextModifed is a method to search a set of rows in a datawindow to find the modified rows within that set. The method takes a buffer parameter and a row parameter. The datawindow buffers are Primary!, Filter!, and Delete!. In general you would only look at the Primary buffer.
ModifedCount is a method to determine the number of rows which have been modifed in a datawindow. Note that deleting a row is not considered a modification. To find the number of rows deleted use the DeletedCount method.
GetItemStatus is a method to get the status of column within a row in a data set in a datawindow. It takes the parameters row, column (name or number), and DWBuffer.
So now an example of using this:
// loop through rows checking for changes
IF dw_dash.Modifiedcount() > 0 THEN
ll = dw_dash.GetNextModified(0,Primary!)
ldw = dw_dash
DO WHILE ll > 0
// watch value changed
IF ldw.GetItemStatus(ll,'watch',Primary!) = DataModified! THEN
event we_post_item(ll, 'watch', ldw)
END IF
// followup value changed
IF ldw.GetItemStatus(ll,'followupdate',Primary!) = DataModified! THEN
event we_post_item(ll, 'followupdate', ldw)
END IF
ll = ldw.GetNextModified(ll,Primary!)
LOOP
ldw.resetupdate() //reset the modifed flags
END IF
In this example we first check to see if any row in the datawindow has been modified. Then we get the first modified row and check if either the 'watch' or 'followupdate' columns were changed. If they were we trigger an event to do something. We then loop to the next modified row and so on. Finally we reset the modified flags so the row would now show as not being mofified.

Setting date value in an Interactive grid based on a page item

I am trying to set a interactive grid column value (which is a date) based on a page item (which is also a date). I have already tried defaulting and using dynamic action set value (jquery seletor) to set item value to the interactive grid column but it does not work how I want it to work.
I have a page item called "P_DEF_DATE" and I want to set a date column in the interactive grid to this value but I want when I change the value in the page item and I click add row on the interactive grid, it must always use whatever value I have in the page item. For example:
P_DEF_DATE = 12-JAN-2021
when I click on add row in the interactive grid, my date column must equal to P_DEF_DATE and i add a few rows based on that date but then i change the date of P_DEF_DATE to:
P_DEF_DATE = 28-JAN-2021
now I want when I click on add row in the interactive grid, I it must show this new date from the page item in the date column in the interactive grid, keeping in mind the page does not refresh and I have rows with the date 12-JAN-2021.
Thank you in advance!
I implemented same few days ago. Following is what I did.
Create Dynamic Action on Row Initialization Event, set Region to your IG
Set True Action to Execute JavaScript Code
Use code
var model = this.data.model,
rec = this.data.record,
meta = model.getRecordMetadata(this.data.recordId);
if ( meta.inserted ) {
model.setValue(rec,"COLUMN_NAME", $v("P_DEF_DATE"));
}
Replace JOB with your column name and P_DEF_DATE with you Item name
More details Here
Also, out of curiosity, why there is no number like P1, P2 in your item name ??

Google Sheets - How to Combine Filter Function with Filter View

I've been working on a spreadsheet with over 100 rows, and found a hacky way to incorporate a "hide" checkbox that will hide any row where column C matches a specific value (building type), specified beside the box. To do this, I first created a function like this: =FILTER(Data!A1, OR(Data!$C1<>$O$2, $P$2)) and dragged that across every row and column in a seperate sheet. This reads as, "Display current cell if the corresponding column C in that row in Data does not match the building type, or if the the checkbox is checked. This way, the whole row is hidden when the building type matches, and the box is unchecked. A1 adjusted to each row individually, $C1 referenced the building's type, $O$2 referenced the targeted type to potentially hide, and $P$2 was the checkbox.
Problem #1: This created a lot of formulas in hundreds of cells, and when the building type was not found, it displayed #N/A across the entire row. A Filter View was able to hide these values, but it was inconvenient to have to reset the values every time I wanted to hide or unhide another building type.
My Attempt to Fix: I used a filter function once again to recreate the entire sheet from one cell, hiding the appropriate rows, using this: =FILTER(Data!A2:J191, ARRAYFORMULA((Data!$C2:C191<>$O$2)+(Data!D2:D191*$P$2)) This is the hacky part. I multiplied the checkbox's "true" by an array arbitrary positive numerical values in the D column to "OR" it with each building type value to achieve the same goal as before, but for EVERY cell.
Problem #2 arose: When I get my beautiful sheet, I can not sort it via a filter view, or it will throw an error and display nothing. I'm resorting to sorting the original tab, but intend to have it be ignored entirely. So how do I combine these two, Filter View, and Filter Function, to create a nice spreadsheet where I can SORT AND HIDE rows?
Bonus Problem #3: To add more buttons, my formula is this: =FILTER(Data!A1:J191, ARRAYFORMULA((Data!$C1:C191<>$O$2)+(Data!D2:D192*$P$2)), ARRAYFORMULA((Data!$C1:C191<>$O$3)+(Data!D2:D192*$P$3)), ARRAYFORMULA((Data!$C1:C191<>$O$4)+(Data!D2:D192*$P$4)), ARRAYFORMULA((Data!$C1:C191<>$O$5)+(Data!D2:D192*$P$5)), ARRAYFORMULA((Data!$C1:C191<>$O$6)+(Data!D2:D192*$P$6)), ARRAYFORMULA((Data!$C1:C191<>$O$7)+(Data!D2:D192*$P$7)), ARRAYFORMULA((Data!$C1:C191<>$O$8)+(Data!D2:D192*$P$8)), ARRAYFORMULA((Data!$C1:C191<>$O$9)+(Data!D2:D192*$P$9))) This is ugly, and very slow to load. Is there a way to create a function range to handle the same checks on multiple rows, and crunch it into a single formula?
Here is another monstrosity (this one has less repetition) for you:
=QUERY(
{IGNORE!A2:J, IGNORE!P2:P},
"SELECT * "
& "WHERE Col3 is not null "
& IF(COUNTIF(P2:P9, False) = 0, "", "AND NOT Col3 MATCHES '^" & JOIN("$|^", IFNA(FILTER(O2:O9, P2:P9 = False))) & "$' ")
& IF(COUNTIF(A2:K2, ">0") = 0, "", "ORDER BY Col" & JOIN(", Col", IFNA(FILTER(COLUMN(A2:K2) & IF(COLUMN(A2:K2) = 1, "", " DESC"), A2:K2)))),
0
)
Your checkboxes should remain. The second row can have just True/False values, no need for column number (a simple change will be needed COUNTIF(A2:K2, ">0") -> COUNTIF(A2:K2, True)). Also consequent sort works now (but only in the actual order of columns: if checked 1, 3, 4 then it will be sorted first by 1, then by 2, then by 4). You could place another config table on the right about sorting, where you would select all the columns you wish to sort by, their mutual order, and desc/asc for them.
Edit: added IFNA so FILTER won't return an error, changed multiple ANDS to MATCHES and simple regexes.

Errors when grouping by list in Power Query

I have a set of unique items (Index) to each of which are associated various elements of another set of items (in this case, dates).
In real life, if a date is associated with an index, an item associated with that index appeared in a file generated on that date. For combination of dates that actually occurs, I want to know which accounts were present.
let
Source = Table.FromRecords({
[Idx = 0, Dates = {#date(2016,1,1), #date(2016,1,2), #date(2016,1,3)}],
[Idx = 1, Dates = {#date(2016,2,1), #date(2016,2,2), #date(2016,2,3)}],
[Idx = 2, Dates = {#date(2016,1,1), #date(2016,1,2), #date(2016,1,3)}]},
type table [Idx = number, Dates = {date}]),
// Group by
Grouped = Table.Group(Source, {"Dates"}, {{"Idx", each List.Combine({[Idx]}), type {number}}}),
// Clicking on the item in the top left corner generates this code:
Navigation = Grouped{[Dates={...}]}[Dates],
// Which returns this error: "Expression.Error: Value was not specified"
// My own code to reference the same value returns {0,2} as expected.
CorrectValue = Grouped{0}[Idx],
// If I re-make the table as below the above error does not occur.
ReMakeTable = Table.FromColumns(Table.ToColumns(Grouped), Table.ColumnNames(Grouped))
in ReMakeTable
It seems that I can use the results of this in my later work even without the Re-make (I just can't preview cells correctly), but I'd like to know if what's going on that causes the error and the odd code at the Navigation step, and why it disappears after the ReMakeTable step.
This happens because when you double click an item, the auto-generated code uses value filter instead of row index that you are using to get the single row from the table. And since you have a list as a value, it should be used instead of {...}. Probably UI isn't capable to work with lists in such a situation, and it inserts {...}, and this is indeed an incorrect value.
Thus, this line of code should look like:
Navigate = Grouped{[Dates = {#date(2016,1,1), #date(2016,1,2), #date(2016,1,3)}]}[Idx],
Then it will use value filter.
This is a bug in the UI. The index the UI calculates is incorrect: it should be 0 instead of [Dates={...}]. ... is a placeholder value, and it generates the "Value was not specified" exception if it is not replaced.

KendoUI Grid Create Columns Programmatically

I have an app with a KendoUI DropDownList that is populated with a list of tables from a database and a grid that is initially set with a columns atrribute of an empty array:
...
columns: []
...
The intent is to select a table from the list, send the table name to the server and have the server return JSON data containing the column names and the data from a "SELECT * FROM table" query. The data comes back as expected and the first time through I can use it as follows where "self" is just a reference to the grid in my view/model:
self.columns.removeAll();
for (var i = 0; i < joOutput["Cols"].length; i++) {
var col = { title: joOutput["Cols"][i], field: joOutput["Cols"][i] };
self.columns.push(col);
}
After extracting my data and assigning it to the grids datasource, the grid displays correctly with the correct column headers and data. However, when I select another table from the list and receive data from the server, the grid display does not update, even though it seems the grid columns have been updated though the execution of the above code. The end the result on screen is the column headers are the names of the columns from the first grid and the number of empty lines from the rows returned from the second query.
This dynamic manipulation of columns seems to be very difficult to do as seen by the forum post at http://www.kendoui.com/forums/ui/grid/dynamically-add-new-column.aspx but that post is over a year old now and I would've hoped some progress would've been made on this now, especially in light on the recent webcast on March 20 for the new release. So I guess the question remains: Is what I'm after even possible or am I SOL? Thanks.
You cannot dynamically change the columns of the grid after initialization. You can however create a new grid instance. Don't forget to call the destroy method of the old grid.

Resources