Crystal reports select critera with comma delimited - crystal-reports

I have a crystal report I need to change the select criteria on. Currently criteria compare's a database field to the parameter I created in the report.
{MaterialCR.MaterialId} = {?MaterialId}
I am now have a field that has comma delimited data in it I need to make sure the parameter includes any of the other ids in the new field.
Materialused has this data in it. "MA0161 ,MA0167" (No double quotes) . This doesn't work
{MaterialCR. MaterialUsed} = {?MaterialId}
I have tried to create a function to compare the two but it does not seem to work. It does not see the parameter as a string array.
My material match function that does not work
Function MaterialMatch (MaterialUsed as string,v1 () As String)
dim MyArray() as string
MyArray = Split (MaterialUsed,"," )
dim Match as boolean
Match = false
dim x as number
For x = 1 To count(v1) Step 1
IF "ALL" in v1 then
Match = true
x = count(MyArray)
end if
if MyArray(x) in v1 then
Match = true
x = count(MyArray)
end if
Next x
MaterialMatch = Match
End Function
This is what the data I am looking at looks like. We have many materials with a Material ID in it. We also have associated time that we need to select. It does not have a material id as it is a many to one situation. I need to retrieve all the records associated with the material including the time. Getting the material with ids is not the issue. I need to get the Time records also. I modified the view this report uses to include the material that overlaps the time. This is where I am stuck.
This is what my select expert formula looks like now. I do know the material used part is wrong.
(
{JobTimeMaterialCR.MaterialId} = {?MaterialId}
or
(
{JobTimeMaterialCR.Type} = "Time"
and
{JobTimeMaterialCR.MaterialUsed} = {?MaterialId}
))

I was able to write a formula that worked for me using the logic I described in my comment. Use this formula as your Record Selection Formula. In Formula Workshop these are found in Selection Formulas > Record Selection.
Local StringVar array values := Split({?Search Values},",");
Local NumberVar indexCount := Count(values);
Local BooleanVar found := false;
Local NumberVar counter;
For counter := 1 to indexCount Step 1 Do
(
If InStr({ARINVT.DESCRIP}, values[counter]) > 0 Then
found := true
);
found;
It's rough, but a good start. The search is case sensitive, so you may need to tweak it with some Lower() functions if you want case insensitive searches. Also, if there is a space between the delim character and the search string in your CSV string, then the space is included in the search. A Replace() function can help you get around this, but that would prevent you from using spaces in the search strings. If you need to use spaces in searches, then just take care when building your CSV String that there are no spaces before or after the comma that is your delim character.
If you need any help understanding the syntax of my formula feel free to comment and I will answer any questions.
I used a parameter field called {?Search Values} to simulate the CSV string data. {ARINVT.DESCRIP} is a field name from my test database I used to search thousands of records for key words I typed into my parameter field. You will want to replace these field names in the formula with your field names and you should be able to get this working without much trouble.

Related

string match and remove each row in a postgresql

So in short:
I need to find all rows in the column Translation that begin with the letter M (M123 is one of the Prefixes) and then I need to remove the M123 and similar prefixes from all the rows.
For example, row 1 contains the following data:
M123 - This is translated from Spanish to English
And I need to remove the M123 - from the mentioned data. And this I need to do for the Translation column in every row in the table.
It's been a while since I actually did some SQL-Queries. So I tried a WHERE clause to find all the M prefixes but my query returns an empty search. Following is the query I am using atm:
SELECT Translation from Translation_Table where Translation like 'M';
I am a little bit confused right now. So any help is appreciated.
I sense that you might be wanting to do an update here, rather than a select:
UPDATE Translation_Table
SET Translation = REGEXP_REPLACE(Translation, 'M[0-9]+', '')
WHERE Translation ~ '^M[0-9]+';
addition to this answer following query will remove all occurence of M[any length of a number]
UPDATE Translation_Table
SET Translation = REGEXP_REPLACE(Translation, '[M[:digit:]]', '', 'g')
WHERE Translation ~ '.M[0-9]*';

What function do I use in a Salesforce apex trigger to trim a text field?

I'm new to writing apex triggers. I've looked through a lot of the apex developer documentation, and I can't seem to find the combination of functions that I should use to automatically trim characters from a text field.
My org has two text fields on the Case object, which automatically store the email addresses that are included in an email-to-case. The text fields have a 255 character limit each. We are seeing errors pop up because the number of email addresses that these fields contain often exceeds 255 characters.
I need to write a trigger that can trim these text fields to the last ".com" before it hits the 255 character limit.
Perhaps I'm going about this all wrong. Any advice?
You can use replace() function in Apex.
String s1 = 'abcdbca';
String target = 'bc';
String replacement = 'xy';
String s2 = s1.replace(target, replacement);
If you need to use regular expression to find the pattern, then you can use replaceAll()
String s1 = 'a b c 5 xyz';
String regExp = '[a-zA-Z]';
String replacement = '1';
String s2 = s1.replaceAll(regExp, replacement);
For more information please refer Apex Reference Guide
The following code I think that covers what you are searching:
String initialUrl = 'https://stackoverflow.com/questions/69136581/what-function-do-i-use-in-a-salesforce-apex-trigger-to-trim-a-text-field';
Integer comPosition = initialUrl.indexOf('.com');
System.debug(initialUrl.left(comPosition + 4));
//https://stackoverflow.com
The main problems that I see are that other extensions are not covered (like ".net" urls) and that urls that have a ".com" appearing previous to the last one (something like "https://www.comunications.com"). But I think that this covers most of the use cases.
Why not increasing the length of that specific field? Trimming the text might cause data loss or unusable. Just go to object manager find that object and that specific field. Edit field and increase the length.

How do you retrieve a date value from a buffer-field in Progress Openedge?

I've got a buffer which contains a mix of data, number and character fields. I am getting the displaying the values of the fields, but for some reason date fields return "?" when I try to add them to a string.
I still get ? even if I do
ASSIGN lvString = lvString + STRING( hField:BUFFER-VALUE ).
I've also tried assigning the BUFFER-VALUE to a local DATE variable, and converting that to a string, but that doesn't work either - still ?.
However if I use the STRING-VALUE attribute, it works fine.
How do I get the value out as a date field, rather than just a string?
There are two ways that you can use to achieve your needs. One is to use directly the table buffer and the other is to use an QUERY handle.
First example using a buffer directly from a table (or a TEMP-TABLE, doesn't matter):
DEF VAR dateVar AS DATE NO-UNDO.
FIND FIRST job NO-LOCK.
dateVar = DATE(BUFFER job:BUFFER-FIELD('dt-job'):BUFFER-VALUE).
MESSAGE dateVar
VIEW-AS ALERT-BOX INFO BUTTONS OK.
Second example using a query handle:
DEF VAR dateVar AS DATE NO-UNDO.
DEF QUERY qrJob FOR job.
OPEN QUERY qrJob FOR EACH job.
QUERY qrJob:GET-FIRST().
dateVar = DATE(QUERY qrJob:GET-BUFFER-HANDLE(1):BUFFER-FIELD('dt-job'):BUFFER-VALUE).
MESSAGE dateVar
VIEW-AS ALERT-BOX INFO BUTTONS OK.
As Tim Kuehn said you can substitute 'dt-job' by # of field in the query if you know its position inside the query. I could used BUFFER-FIELD(2) in substitution of BUFFER-FIELD('dt-job') because dt-job is the #2 field in my query. Keep in mind that use the FIELDS clause in a FOR EACH or in an OPEN QUERY statement changes the order of fields in query. Generally, for browsers only available the columns fields specified in FIELDS section, in order.
These might work for you. It's important to say that BUFFER-VALUE always returns a CHARACTER data type and because of this you need to use DATE statement for data conversion.
Hope it helps.
The standard form for getting a data of the field's data type is
buffer table-name:buffer-handle:buffer-field("field-name"):buffer-value.
for arrays it's:
buffer table-name:buffer-handle:buffer-field("field-name"):buffer-value[array-element].
You can also substitute a field # for "field-name" to get the buffer field handle.

How can I do breaks and subtotals in a report?

I need to generate a business report using perl + Template Toookit and LaTeX.
Things are working really well, but I am struggling with the problem of having breaks (for example page breaks, or special headers) and subtotals whenever a field changes.
So, for example, every time the field "category" changes, I'd need to have a total of sales for that category, and a header showing that another category listing is starting; and then do the same when the field "group" - with the added interest that "group" is made up of categories, so the two things should nest.
I guess anyone that has built reports with Microsoft Access (or probably any other business reporting application) should be familiar with the problem.
Ideally this would be solved at a meta-level, so I don't have to rebuild the code every time, but only to specify what fields should generate breaks or subtotals.
I am (voluntarily) constrained to LaTeX and TT: LaTeX because of the control it gives over typography, and the possibility of generating custom graphics, and TT (or anything else that works in perl) because of learning curves.
There's no built-in subtotaling feature in TT, but you could possibly put your data into a Data::Table object, that would give you some ability to handle subtotaling at the 'meta' level, as you say.
Depending on the number of columns involved though, it might be just as simple to create local hashes to maintain running totals: NB: untested, example code only
[%-
MACRO printrow(rowtype, line) BLOCK;
# however you print the row as LaTeX
# rowtype is 'row', 'subtotal' or 'grandtotal' for formatting purposes
END;
SET sumcols = [ 'col3', 'col4', 'col5' ]; # cols to be accumulated
SET s_tot = {}; SET g_tot = {};
FOREACH i IN sumcols;
SET s_tot.$i = 0; # initialise
SET g_tot.$i = 0;
END;
FOREACH row IN data;
IF s_tot.col2 AND s_tot.col2 <> row.col2; # start of new group
printrow('subtotal', s_tot);
FOREACH i IN sumcols;
SET s_tot.$i = 0; #re-init
END;
END;
printrow('row', row);
SET s_tot.col2 = row.col2; # keep track of group level
FOREACH i IN sumcols;
SET s_tot.$i = s_tot.$i + row.$i;
SET g_tot.$i = g_tot.$i + row.$i;
END;
END;
printrow('grandtotal', g_tot);
-%]
Of course, if you have more than a couple of grouping levels, this can get quite messy. You could make s_tot an array of hashes to manage each level, to avoid hard-coding the levels. That's left as an exercise for the reader, as they say.

Crystal Reports: Create Array or get values from a column

Say I'm working on a report, on a column called someTable.someColumn. What I need is to have all of the values in the ReportHeader. I know I cound create a subreport, pass them this column and iterate it in the details, but I would like to know if it's possible to do it without a subreport.
If I use the following, I get the right result, which in my case is 9:
COUNT(someTable.someColumn)
I also tried the following, but it doesn't work - it only takes one of the 9 values randomly.
Local NumberVar i := 0;
Local StringVar Array items := {someTable.someColumn};
Local StringVar output := "";
while (i < count(items)) do (
i := i+1;
output := output + items[i];
);
output;
Is it possible to iterate over a column in order to get the values?
You can't do this in the report header. You have to use the detail section to read each value.
The only solution which springs to mind is using a subreport. Although you wouldn't pass them this column and iterate it in the details. Because it would only pass the first value from the column. You would pass it the report parameters which it could use to obtain the column values from the database the same way your main report does.
I haven't found a way to do this in the report header, but you could put it in your report footer with the following formula:
global StringVar output;
output := output + {someTable.someColumn} + ",";
This will execute each time someTable.someColumn changes over the course of report generation, and append it to the global variable. Unfortunately, it doesn't keep all instances of it up to date - for example, if you include it in the report details somewhere, you'll be able to see the evolution of output over the course of the report. In the header, it'll only display the first value.
Note: You won't want to set output := "" in this formula, as that'll reset the value each time. It seems, though, that Crystal automatically initializes the variable for you when it's created, and I didn't run into any errors with only the above formula (i.e, I didn't need to create a second formula to initialize output). I've also included a delimeter (+ ","), to help separate each of the values, but you can easily just remove that.