Parsing XML in Crystal Reports Formula Language - xml-parsing

I have an XML file i just imported into Crystal Reports 2016 as an ADO.NET (XML) DataSet .
I'm trying to parse some of the information on the DataSet i only get one entry on the xml instead of the list i desire to get .
<Problem>
<Person>
<Name>
<FirstName> Clausen </FirstName>
</Name>
</Person>
<Person>
<Name>
<FirstName> Mario </FirstName>
</Name>
</Person>
</Problem>
On Crystal Reports formula Workshop i've tried using the code :
whileprintingrecords;
stringvar name := {Person.Name};
And what i get is just the last name
After searching the internet i found this For loop:
whileprintingrecords;
stringvar array x := split({Person.Name},"</");
numbervar i:= 0 ;
numbervar j := unbound(x);
stringvar array y;
numbervar k ;
for i := 1 to j do(
if instr(x[i],"<Name>") <> 0 then(
k := k+1;
redim preserve y[j];
y[k] := extractstring(x[i],"<Name>","</Name>")) [i]);
stringvar Name := y[k];
After trying both codes i only get the last name instead of the two i want.

Related

Retrieving second word to last but one word in a sentence in plsql

I have written a program which executes properly in plsql but the output is wrong. Logically I donot see any issue with the code. Here is the code:
begin
inpstr := rtrim(ltrim(regexp_replace(inp,'\s{2,}','')));
lastpos := instr(inpstr,' ',-1);
out3 := SUBSTR(inpstr, INSTR(inpstr,' ',-1) + 1);
pos := instr(inpstr,' ');
out1 := substr(inpstr,1,pos);
out2 := substr(inpstr,pos,lastpos);
end;
O/P:
dbms_output.put_line('First Word:: '||out1||' '||'Second Word:: '||out2||' '||'Lastword:: '||out3);
PROCEDURE SPLITWORDS compiled
anonymous block completed
First Word:: Welcome Second Word:: to the world of analyti Lastword:: analytics!
But the second word should retrieve 'to the world of' but it fetches analyti.
Could anyone tell me whats wrong with my code.
Thanks,
Dex.
When you assign out2, you at least have to substract pos from lastPos.
Because lastPos in your sample-text "Welcome to the world of analytics!" will be 24 and pos will have 8, so the substring from pos 8 with a length of 24 is ... right: " to the world of analyti"
The third parameter of the substr function is the length of the substring, not the location of the ending character. Subtracting pos from lastpos (see below) would allow your code to work.
out2 := substr(inpstr, pos, lastpos - pos);

Delphi Outlook Contact Automation - Iterate thru ALL properties of a ContactItem

I am currently writing a small program to extract ALL data elements of my Outlook contacts to a new CRM database. I have imported the necessary type library and came up with the following code (It's almost there!!!)
`
Contacts := NameSpace.GetDefaultFolder(olFolderContacts);
for i := 1 to Contacts.Items.Count do
begin
Contact := Contacts.Items.Item(i);
{now you can read any property of contact. For example, full name and
email address}
// ShowMessage(Contact.FullName + ' <' + Contact.Email1Address + '>');
Memo1.Lines.Add(Contact.FullName + ' <' + Contact.Email1Address + '>');
Memo1.Lines.Add(IntToStr(Contact.ItemProperties.Count) + '>');
for j := 0 to Contact.ItemProperties.Count -1 do
if Contact.ItemProperties.Item(j) <> null then
Memo1.Lines.Add(Contact.ItemProperties.Item(j));
end;
Iterating thru the contacts works OK (I see them in the Memo). My problem is the 2nd "for" loop in trying to check ALL 168 fields of the contact (the 168 shows in the memo too)
Can anyone help shed some light on iterating thru each Property of each contact item? I have found some answers but I need/want to drill down further.
Thanks in advance
Bill
Your comparison to null in that way might be the problem. Try:
for j := 0 to Contact.ItemProperties.Count -1 do
Memo1.Lines.Add(Contact.ItemProperties.Item(j).Name);
or even:
for j := 0 to Contact.ItemProperties.Count -1 do
if Contact.ItemProperties.Item(j).Name <> null then
Memo1.Lines.Add(Contact.ItemProperties.Item(j).Name);
I am not sure but you can even try to access the items in ItemProperties like:
Contact.ItemProperties[j].Name
OK, after spending some quality time in the TLB for office I was able to walk the properties of each contact whether useful or not. The RTFBody property had to be converted from Unicode to ANSI WideString, the attachments as a collection (count was there so easy enough to iterate), and dispatch values I just bypassed. Learned a lot, MSDN Office Interop online docs provided good help in handling field types. The long handed dot notation was necessary because I could not seem to get grouping to work but stepping down each level worked just fine. The important parts follow. As always thanks for the input.
Memo1.Lines.Add(IntToStr(Contacts.Items.Count) + '>');
for i := 1 to Contacts.Items.Count do
begin
Contact := Contacts.Items.Item(i);
{now you can read any property of contact. For example, full name and
email address}
for j := 0 to Contact.ItemProperties.Count -1 do
begin
ContactProperty := Contact.ItemProperties.Item(j);
if not VarIsNull(ContactProperty.Value) then
if ContactProperty.Name = 'RTFBody' then
begin
RTFByte := ContactProperty.Value;
SetString(tANSIStr, PAnsiChar(#RTFByte[0]), Length (ContactProperty.Value));
Memo1.Lines.Add(ContactProperty.Name + ' <' + tANSIstr + '>');
RichEdit1.Lines.Add(tANSIstr);
end
else
if ContactProperty.Name = 'Attachments' then
begin
Attachments := Contact.Attachments;
for k := 1 to Attachments.Count do
begin
ContactAttachment := Attachments.Item(k);
Memo1.Lines.Add('Attachment.FileName <' + ContactAttachment.FileName + '>');
end;
end
end;

Can I use an If statement inside a While statement?

while not eof(MyFile) do
begin
Readln(MyFile,sLine);
iCheck := pos('*',sLine);
if iCheck >= 0 then
K := K + 1;
else
K := 1;
sLine := sArrayParty[K];
end;
K is my counter. MyFile is set to a textfile.
I am trying to run an if statement inside a while statement to check if there is a * in a line read into sLine. If so, I want my counter to be incremented, thereby putting the following text into the next index of the array. So basically I have a text file with information separated by * as delimiters and I want each piece of information to populate a new index. But delphi spases everytime I put that if statement in.
You have a clear syntax error in your code, and the compiler explains exactly what it is:
[DCC Error] Unit1.pas(22): E2153 ';' not allowed before 'ELSE'
So read the words the error message contain, and remove the ; before the else:
if iCheck > 0 then
K := K + 1
else
K := 1;
The number in parenthesis after the Unit1.pas (in my example, (22) is the exact line number where the compiler stopped working, so the line before the else would be line 21. The line numbers at the bottom of the editor window tell you what line that is clearly.
if there is no '' then the pos function will return 0,
if there is '' then it will return the first occurance position.
if iCheck >= 0 then
should be changed to if iCheck > 0 then
i do remember we can assign the string to a string list and assign the stringlist's delimiter property to '*'
ie.
strlst.delimiter := '*';
strlst.text := sline;
so u can get each string traversing through the strlst...
(i used this long back,and i dont have delphi now to test it,please correct me if any thing is wrong)

Indexes order in Delphi?

I'm basically coding some sort of table where for column tags I have some numbers and for row tags I have some strings which contain such numbers separated by commas.
I'm taking all the row tags from a TString named minterms_essentials and the column tags from one named minterms.
First I must tag the created 2 dimensions array. And then, if any string from the rows contains certain letter, I must place an 'x' in the proper column.
I've wrote this Delphi code but I'm getting access violation so far...
SetLength(tabla, minterms_essentials.Count+1,minterms.Count+1);
for i := 0 to minterms.Count-1 do
begin
tabla[0,i+1] := IntToStr(BinToInt(minterms[i]));
end;
for i := 0 to minterms_essentials.Count-1 do
begin
tabla[i+1,0] := minterms_essentials[i];
end;
for i := 1 to minterms_essentials.Count-1 do
begin
for g := 1 to minterms.Count-1 do
begin
ss := tabla[g,0].Split([',']);
for s in ss do
begin
if s = tabla[0,g] then
begin
tabla[g,i] := 'x';
end;
end;
end;
end;
Is there any better and correct way to do this?
Look at this:
first dimension is defined by minterms_essentials
SetLength(tabla, minterms_essentials.Count+1,minterms.Count+1);
but here you are using minterms to index first dimension of array:
for g := 1 to minterms.Count-1 do
begin
ss := tabla[g,0].Split([',']);
P.S. Have you still not turned on range check?

Simple Delphi DBcharting

So, the problem I'm having is that I'm displaying two bars on the graph for each student, I just want one of them. They're the correct height though, so that's good.
This is my Delphi source code;
strlstField := TStringList.Create();
ADOQGetResults.SQL.clear;
ADOQGetResults.SQL.Add(
'SELECT Results.StudentID, SUM(Results.Rawmark) as TRM, StudentInfo.Fname '+
'FROM (StudentInfo INNER JOIN Results ON StudentInfo.StudentID = Results.StudentID) '+
'WHERE (((StudentInfo.StudentID)=Results.StudentID)) AND Results.TestID =12 '+
'GROUP BY StudentInfo.Fname, Results.StudentID'
);
ADOQGetResults.Active := True;
ADOQGetResults.Open;
DBChart1.Title.Text.Clear;
DBChart1.Title.Text.Add('Class leaderboard');
DBChart1.Title.Font.Size := 15;
DBChart1.LeftAxis.Title.Font.Size := 12;
DBChart1.LeftAxis.Title.Caption := 'Total marks';
DBChart1.BottomAxis.Title.Font.Size := 12;
DBChart1.BottomAxis.Title.Caption := 'Student';
//Charting Series
//To Remove Old Series
for intCnt := DBChart1.SeriesCount -1 downto 0 do
DBChart1.Series[intCnt].Free;
//To Add New Series
for intCnt := 1 to ADOQGetResults.FieldCount - 1 do
begin
strlstField.Add(ADOQGetResults.FieldList[intCnt].FieldName);
DBChart1.AddSeries(TBarSeries.Create(nil));
end;
//To set source for Series
for intCnt:= 0 to DBChart1.SeriesCount -1 do
begin
with DBChart1 do begin
Series[intCnt].Clear;
Series[intCnt].Title := strlstField[intCnt];
Series[intCnt].ParentChart := DBChart1;
Series[intCnt].DataSource := ADOQGetResults;
Series[intCnt].XLabelsSource := 'Fname';
Series[intCnt].YValues.ValueSource := 'TRM';
end;
end;
I've been trying to work-out whats going wrong all day, so if anyone can help at all I'd be very grateful!
Here is what the graph looks like right now;
http://oi48.tinypic.com/6qelba.jpg
Why are you looping over EVERY FIELD in the result (you return 3 fields in your query) and adding one series PER field in the result? It's almost like you think that the field count equals your row count or something. Secondly I would venture to guess that something in your query plus your data (that we can't see) could result in you getting more rows in your query result than you were expecting.
Why are you destroying and re-adding series when your query always returns 3 fields, 1 field is not charted, 1 field is the series label source and 1 field is the series value source? Just statically create one series at designtime in your dfm and forget all this crazy runtime stuff. Have you tried double clicking dbchart and adding ONE BarChart series there?
This works and is much less code. You don't need to open a dataset twice, by the way. Note that I'm using the DBDEMOS.mdb database that comes with Delphi here so that everyone can play along. Add a db chart and at DESIGNTIME add ONE barchart series to it. Configure as desired. Use this code. dataset below is a TADODataset.
-
dataset.CommandText := 'select EmpNo,FirstName,Salary from employee';
dataset.Active := True;
DBChart1.Title.Text.Clear;
DBChart1.Title.Text.Add('Class leaderboard');
DBChart1.Title.Font.Size := 15;
DBChart1.LeftAxis.Title.Font.Size := 12;
DBChart1.LeftAxis.Title.Caption := 'Total marks';
DBChart1.BottomAxis.Title.Font.Size := 12;
DBChart1.BottomAxis.Title.Caption := 'Student';
if DBChart1.SeriesCount<1 then
begin
raise Exception.Create('Add series to your chart in the dfm ONCE.');
end;
//To set source for Series
with DBChart1 do begin
Series[0].Title := 'Test';
Series[0].DataSource := dataset;
Series[0].XLabelsSource := 'FirstName';
Series[0].YValues.ValueSource := 'Salary';
end;
Note that this is still more code than you absolutely have to write. You could do most of this if not all in dfm (form designer).

Resources