I have more rows. And i want for the rows with status AA1 a column protected and for the rows with status different than AA1 the same column unprotected.
So I wrote this:
ll_count = dw_list.RowCount()
if ll_count > 0 then
for i = 1 to ll_count
if dw_list.object.status[i] = 'AA1' then
dw_list.modify("f_change[i].Protect='1")
//dw_list.Object.f_change[i].modify("f_change[i].Protect='1")
dw_list.Object.f_change[i].Background.Color = gf_get_btnface()
end if
if dw_list.object.status[i] <> 'AA1' then
dw_list.modify("f_change[i].Protect='0'")
end if
next
end if
But dw_list.modify("f_change[i].Protect='1'") is not correct. Neither dw_list.Object.f_change[i].modify("f_change[i].Protect='1").
If I just write dw_list.modify("f_change.Protect='1'") it modifies all the rows.
I woud do this without programming a single line, but by editing the datawindow design.
Open the datawindow in design mode
Select the desired column
In the 'General' tab, click on the small icon nearby 'Protect'.
Insert there the condiction to protect or not that column: if( status = 'AA1', '0', '1')
Done for all your data.
The same process can be applied to many characteristics of data window columns (color, background color, visible, pointer, position,...)
Alternatively, you could put the condition programmatically, but I would only do it if you need to change the protection scheme 'on the fly'. Anyway, the principle is to set the protect condition on the column itself.
Generally speaking, try to do in PowerBuilder as much as you can WITHOUT script programming. U
Related
Goal: I have a bunch of keywords I'd like to categorise automatically based on topic parameters I set. Categories that match must be in the same column so the keyword data can be filtered.
e.g. If I have "Puppies" as a first topic, it shouldn't appear as a secondary or third topic otherwise the data cannot be filtered as needed.
Example Data: https://docs.google.com/spreadsheets/d/1TWYepApOtWDlwoTP8zkaflD7AoxD_LZ4PxssSpFlrWQ/edit?usp=sharing
Video: https://drive.google.com/file/d/11T5hhyestKRY4GpuwC7RF6tx-xQudNok/view?usp=sharing
Parameters Tab: I will add words in columns D-F that change based on the keyword data set and there will often be hundreds, if not thousands, of options for larger data sets.
Categories Tab: I'd like to have a formula or script that goes down the columns D-F in Parameters and fills in a corresponding value (in Categories! columns D-F respectively) based on partial match with column B or C (makes no difference to me if there's a delimiter like a space or not. Final data sheet should only have one of these columns though).
Things I've Tried:
I've tried a bunch of things. Nested IF formula with regexmatch works but seems clunky.
e.g. this formula in Categories! column D
=IF(REGEXMATCH($B2,LOWER(Parameters!$D$3)),Parameters!$D$3,IF(REGEXMATCH($B2,LOWER(Parameters!$D$4)),Parameters!$D$4,""))
I nested more statements changing out to the next cell in Parameters!D column (as in , manually adding $D$5, $D$6 etc) but this seems inefficient for a list thousands of words long. e.g. third topic will get very long once all dog breed types are added.
Any tips?
Functionality I haven't worked out:
if a string in Categories B or C contains more than one topic in the parameters I set out, is there a way I can have the first 2 to show instead of just the first one?
e.g. Cell A14 in Categories, how can I get a formula/automation to add both "Akita" & "German Shepherd" into the third topic? Concatenation with a CHAR(10) to add to new line is ideal format here. There will be other keywords that won't have both in there in which case these values will just show up individually.
Since this data set has a bunch of mixed breeds and all breeds are added as a third topic, it would be great to differentiate interest in mixes vs pure breeds without confusion.
Any ideas will be greatly appreciated! Also, I'm open to variations in layout and functionality of the spreadsheet in case you have a more creative solution. I just care about efficiently automating a tedious task!!
Try using custom function:
To create custom function:
1.Create or open a spreadsheet in Google Sheets.
2.Select the menu item Tools > Script editor.
3.Delete any code in the script editor and copy and paste the code below into the script editor.
4.At the top, click Save save.
To use custom function:
1.Click the cell where you want to use the function.
2.Type an equals sign (=) followed by the function name and any input value — for example, =DOUBLE(A1) — and press Enter.
3.The cell will momentarily display Loading..., then return the result.
Code:
function matchTopic(p, str) {
var params = p.flat(); //Convert 2d array into 1d
var buildRegex = params.map(i => '(' + i + ')').join('|'); //convert array into series of capturing groups. Example (Dog)|(Puppies)
var regex = new RegExp(buildRegex,"gi");
var results = str.match(regex);
if(results){
// The for loops below will convert the first character of each word to Uppercase
for(var i = 0 ; i < results.length ; i++){
var words = results[i].split(" ");
for (let j = 0; j < words.length; j++) {
words[j] = words[j][0].toUpperCase() + words[j].substr(1);
}
results[i] = words.join(" ");
}
return results.join(","); //return with comma separator
}else{
return ""; //return blank if result is null
}
}
Example Usage:
Parameters:
First Topic:
Second Topic:
Third Topic:
Reference:
Custom Functions
I've added a new sheet ("Erik Help") with separate formulas (highlighted in green currently) for each of your keyword columns. They are each essentially the same except for specific column references, so I'll include only the "First Topic" formula here:
=ArrayFormula({"First Topic";IF(A2:A="",,IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))) & IFERROR(CHAR(10)®EXEXTRACT(REGEXREPLACE(LOWER(B2:B&C2:C),IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))),""),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))))})
This formula first creates the header (which can be changed within the formula itself as you like).
The opening IF condition leaves any row in the results column blank if the corresponding cell in Column A of that row is also blank.
JOIN is used to form a concatenated string of all keywords separated by the pipe symbol, which REGEXEXTRACT interprets as OR.
IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))) will attempt to extract any of the keywords from each concatenated string in Columns B and C. If none is found, IFERROR will return null.
Then a second-round attempt is made:
& IFERROR(CHAR(10)®EXEXTRACT(REGEXREPLACE(LOWER(B2:B&C2:C),IFERROR(REGEXEXTRACT(LOWER(B2:B&C2:C),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>""))))),""),JOIN("|",LOWER(FILTER(Parameters!D3:D,Parameters!D3:D<>"")))))
Only this time, REGEXREPLACE is used to replace the results of the first round with null, thus eliminating them from being found in round two. This will cause any second listing from the JOIN clause to be found, if one exists. Otherwise, IFERROR again returns null for round two.
CHAR(10) is the new-line character.
I've written each of the three formulas to return up to two results for each keyword column. If that is not your intention for "First Topic" and "Second Topic" (i.e., if you only wanted a maximum of one result for each of those columns), just select and delete the entire round-two portion of the formula shown above from the formula in each of those columns.
I'm using the Birt list element to display my data from left to right. (see this question as reference). Eg. List element with a Grid in details and the grid set to inline.
The issue I'm facing now is, that the different rows in the grid are not aligned left to right (probably due to some rows having empty values in some fields). How can I force BIRT to align properly?
EDIT:
This is especially also a problem with longer text that wraps to more than 1 line. The wrapping /multiple lines should be reflected by all list elements in that "row of the output".
Unfortunately, I don't see any chance to accomplish this easily in the generic case - that is, if the number of records is unknown in advance, so you'd need more than one line:
student1 student2 student3
student4 student5
Let's call those line "main lines". One main line can contain up to 3 records. The number 3 may be different in your case, but we can assume it is a constant, since (at least for PDF reports) the paper width is restricted.
A possible solution could work like this:
In your data set, add two columns for each row: MAIN_LINE_NUM and COLUMN_NUM, where the meaning is obvious. For example, this could be done with pure SQL using analytic functions (untested):
select ...,
trunc((row_number() over (order by ...whatever...) - 1) / 3) + 1 as MAIN_LINE_NUM,
mod(row_number() over (order by ...whatever...) - 1), 3) +1 as COLUMN_NUM
from ...
order by ...whatever... -- The order must be the same as above.
Now you know where each record should go.
The next task is to transform the result set into a form where each record looks like this (for the example, think that you have 3 properties STUDENT_ID, NAME, ADDRESS for each student):
MAIN_LINE
STUDENT_ID_1
NAME_1
ADDRESS_1
STUDENT_ID_2
NAME_2
ADDRESS_2
STUDENT_ID_3
NAME_3
ADDRESS_3
You get the picture...
The SQL trick to achieve this is one that one should know.
I'll show this for the STUDENT_ID_1, STUDENT_ID_2 and NAME_1 column as an example:
with my_data as
( ... the query shown above including MAIN_LINE_NUM and COLUMN_NUM ...
)
select MAIN_LINE_NUM,
max(case when COLUMN_NUM=1 then STUDENT_ID else null end) as STUDENT_ID_1,
max(case when COLUMN_NUM=2 then STUDENT_ID else null end) as STUDENT_ID_2,
...
max(case when COLUMN_NUM=1 then NAME else null end) as NAME_1,
...
from my_data
group by MAIN_LINE_NUM
order by MAIN_LINE_NUM
As you see, this is quite clumsy if you need a lot of different columns.
On the other hand, this makes the output a lot easier.
Create a table item for your dat set, with 3 columns (for 1, 2, 3). It's best to not drag the dataset into the layout. Instead, use the "Insert element" context menu.
You need a detail row for each of the columns (STUDENT_ID, NAME, ADDRESS). So, add two more details rows (the default is one detail row).
Add header labels manually, if you like, or remove the header row if you don't need it (which is what I assume).
Remove the footer row, as you probably don't need it.
Drag the columns to the corresponding position in your table.
The table item should look like this now (data items):
+--------------+--------------+-------------+
+ STUDENT_ID_1 | STUDENT_ID_2 | STUDENT_ID3 |
+--------------+--------------+-------------+
+ NAME_1 | NAME_2 | NAME_3 |
+--------------+--------------+-------------+
+ ADDRESS_1 | ADDRESS_2 | ADDRESS_3 |
+--------------+--------------+-------------+
That's it!
This is one of the few examples where BIRT sucks IMHO in comparison to other tools like e.g. Oracle Reports - excuse my Klatchian.
I have in a game a lot of check boxes, that needs a set of rules. There is a rule, which is a one cross check box only should be there in one row of the whole matrix. I pictured the problem as a 2D array, and just check each row/column. Is there a faster way or a better approach, because there will be a lot of IFs, ELSEs..
It'll depend a lot on how you're representing your matrix... If I understood your problem, the easiest way is to simply make a loop, and for each row, count the number of checks checked. So:
for each row:
if col1 = is checked, check++
if col2 = is checked, check++
if col3 = is checked, check++
if check > 1 tell the user that there is an error.
end for
If you change your matrix to store a 0 value for unchecked and 1 for checked, you could test it like:
for each row:
if col1 + col2 + col3 > 1 tell the user that there is an error
end for
I have issues with cell protection.
I would like to protect just one column, B for example.
So I tried:
$sheet->getProtection()->setSheet(true);
$highestRow = $sheet->getHighestRow();
$sheet->getStyle('A1:J2000)->getProtection()->setLocked( PHPExcel_Style_Protection::PROTECTION_UNPROTECTED );
for($i=1;$i<=$highestRow;$i++)
{
$sheet->getStyleByColumnAndRow(1,$i)->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_PROTECTED);
}
But it's really slow, and not good because if I need to open my sheet again
$highestRow = $sheet->getHighestRow(); will return "J".
Another solution would be to get the last non-empty column, do you know how to do that? Because getHighestRow(Column) return the columns unprotected or empty.
The loop is slow because you're applying the style to each individual cell, rather than to the range of cells demonstrated in your
$sheet->getStyle('A1:J2000)->getProtection()->setLocked( PHPExcel_Style_Protection::PROTECTION_UNPROTECTED );
line
: one call to set the style for a range of 1000 cells is more that 1000 times faster than applying it to each of 1000 cells individually.
$sheet->getHighestDataRow();
will return the highest row in the worksheet that contains actual data values
$sheet->getHighestDataColumn();
is the column equivalent
First you can protect complete sheet. After that you can uprotect others. This code will protect the first column and first
$objPHPExcel->getActiveSheet()->getProtection()->setSheet(true);
$objPHPExcel->getActiveSheet()->getStyle('B2:Z400')->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED);
I have a bunch of cells whose font size I'd like to tweak if their content is overflowing, until it all fits. I'd like to write a macro to do this, unless there's a conditional formatting or other formulaic way of doing it. Is there a property that tells whether a cell is overflowing? If so, what is it?
'open office 3
'get current document
oDoc = ThisComponent
' get first work sheet
oSheet = oDoc.getSheets().getByIndex(0)
'first cell in the work sheet
Cell = oSheet.getCellByPosition(0, 0)
MsgBox Cell.CharHeight
Happy Coading :))