Page 1 of 1
Merge style problem
Posted: Sat Jan 22, 2011 10:18 pm
by futuremode
Hi I have a mail merge setup using modifications of your cde. It is working. But the style of the data that replaces the tag is the same as the tag style. The replaced text is compressed to fit in the width of the original tag. I attempted to change the style of the tag which worked to a point but I have Chinese installed it converted the resulting text to chinese not English. The language chosen by the op system is still English though.
I use the following to insert the tag.
Code: Select all
li := TRVLabelItemInfo.CreateEx(RichViewEdit1.RVData, RichViewEdit1.CurTextStyleNo, frmTagList.tmsAvailableTags.Cells[1, frmTagList.tmsAvailableTags.Row]);
li.Tag := Integer(StrNew(PChar(frmTagList.tmsAvailableTags.Cells[1, frmTagList.tmsAvailableTags.Row])));
RichViewEdit1.InsertItem(frmTagList.tmsAvailableTags.Cells[1, frmTagList.tmsAvailableTags.Row], li);
I use the following to insert the data i.e. replace the tag.
Code: Select all
RVData.GetItem(i).StyleNo := 0; //Attempt to change style but get chinese. Get the change style but in Chinese not English
TRVLabelItemInfo(RVData.GetItem(i)).Text := GetFieldValueFromDatabase(FieldName);
vText := RVData.GetItemText(i); // Tested to make sure the vaule was inserted into the document OK.
The variable vText holds the correct English value of the data. But when displayed in RichView it is in Chinese characters. Language font is switched somewhere prior to writing the screen.
I am not setting the display style properly. Not sure what to do here.
Posted: Sun Jan 23, 2011 5:48 pm
by Sergey Tkachenko
LabelItem displays text specified in its Text property.
It does not display and does not use the text that is get/set using GetItemText/SetItemText - this is a different text string! This text is specified in the first parameter of InsertItem, and not used by non-text items.
Posted: Sun Jan 23, 2011 9:10 pm
by futuremode
I replaced the above with;
Code: Select all
RVData.GetItem(i).StyleNo := 0;
RVData.SetItemText(i, GetFieldValueFromDatabase(FieldName));
vText := RVData.GetItemText(i);
The result is again in Chinese. However it appears to have the correct number of characters as per the data now. If I remove the line
The tags are not replaced.
Posted: Mon Jan 24, 2011 5:11 pm
by Sergey Tkachenko
1) The line
is wrong if the i-th item is a label item. Moreover, it can corrupt a document, because it is expected that for label items, StyleNo equals to rvsLabel.
The correct code is
RVData.GetItem(i).TextStyleNo := 0;
2) SetItemText/GetItemText works with visible text only for text items, not for label items! If you need to change visible text in a label item, use TRVLabelItemInfo(RVData.GetItem(i)).Text
Posted: Mon Jan 24, 2011 10:13 pm
by futuremode
I tried
Code: Select all
RVData.GetItem(i).TextStyleNo := 0; .
but TextStyleNo appears to not be an option as it is an undeclared identifier.
Posted: Mon Jan 24, 2011 11:27 pm
by futuremode
I realised it was supposed to be:
Code: Select all
TRVLabelItemInfo(RVData.GetItem(i)).TextStyleNo := 0;
This did not affect the text style however.
Can I email you a graphic of what is happening. The data is merging okay but the resulting text is being compressed or stretched to the length of the label. If I select it and make it bold and then unbold it it changes to the proper size.
Posted: Tue Jan 25, 2011 9:31 am
by Sergey Tkachenko
If possible, it's better to send a simple project reproducing the problem.
What email account do I use?
Posted: Tue Jan 25, 2011 11:31 am
by futuremode
Hi how to I send the project to you. I sent emails to
[email protected] but they bounced back.
Posted: Tue Jan 25, 2011 3:33 pm
by Sergey Tkachenko
Received.
After changing properties of TRVLabelItemInfo (such as Text or TextStyleNo), call its Changed method:
Code: Select all
TRVLabelItemInfo(RVData.GetItem(i)).Text := GetFieldValueFromDatabase(FieldName);
TRVLabelItemInfo(RVData.GetItem(i)).TextStyleNo := 0;
TRVLabelItemInfo(RVData.GetItem(i)).Changed;
Thanks
Posted: Tue Jan 25, 2011 8:05 pm
by futuremode
That fixed it. Thanks
Posted: Tue Jan 25, 2011 9:05 pm
by futuremode
I also added some code to find the style prior to the tag so the text inserted is the style of the item prior to the tag;
Code: Select all
Offs := RichViewEdit1.GetOffsBeforeItem(i);//Get item's position
RichViewEdit1.SetSelectionBounds(i, Offs, i, Offs);//move the caret there.
RichViewEdit1.Invalidate;
StyleNo := RVData.GetItemStyle(i - 1);//move the caret to the item prior to the tag and get its style.
TRVLabelItemInfo(RVData.GetItem(i)).Text := GetFieldValueFromDatabase(FieldName);
TRVLabelItemInfo(RVData.GetItem(i)).TextStyleNo := 0;
TRVLabelItemInfo(RVData.GetItem(i)).Changed;
TRVLabelItemInfo(RVData.GetItem(i)).TextStyleNo := StyleNo;
TRVLabelItemInfo(RVData.GetItem(i)).Changed;
RichViewEdit1.Modified := True;//set the modified flag for the save dialog
It seems to be working fine. I assume the code is okay here. Let me know if I have missed something. Thanks again for your help
Posted: Tue Jan 25, 2011 9:30 pm
by Sergey Tkachenko
This code has several important problems.
1) The item is in RVData. RVData may be a table cell, it is not necessary the main editor.
So, if you want to move the caret before this item, the code should be
Code: Select all
Offs := RVData.GetOffsBeforeItem(i);
RVData := RVData.Edit;
TCustomRVFormattedData(RVData).SetSelectionBounds(i, Offs, i, Offs);
However, why do you need to move the caret? It only would slow down FillFields and add flickering. I suggest to remove this code.
2) The line
Code: Select all
StyleNo := RVData.GetItemStyle(i - 1)
has problems as well.
What if i=0? What if the previous item is a non-text item?
I suggest using this function instead:
Code: Select all
function GetClosestTextStyleNo(RVData: TCustomRVData; ItemNo: Integer);
var i: Integer;
begin
Result := 0;
for i := ItemNo-1 downto 0 do
if RVData.GetItemStyle(i)>=0 then begin
Result := RVData.GetItemStyle(i);
exit;
end;
for i := ItemNo+1 to RVData.ItemCount-1 do
if RVData.GetItemStyle(i)>=0 then begin
Result := RVData.GetItemStyle(i);
exit;
end;
end;
Now, you can call
Code: Select all
StyleNo := GetClosestTextStyleNo(RVData, i);
Posted: Wed Jan 26, 2011 11:28 am
by futuremode
Thanks for that Sergey. Glenn
Posted: Wed Jan 26, 2011 11:39 pm
by futuremode
I modified it so you can set the style in a cell by putting a preceeding space holding the style then delete from the cell after the data has been entered. That way each item in the cell can have its own style different style.
Code: Select all
procedure TForm3.FillFields(RVData: TCustomRVData);
var i,r,c, StyleNo : Integer;
Table: TRVTableItemInfo;
FieldName : String;
begin
for i := 0 to RVData.ItemCount - 1 do
begin
case RVData.GetItemStyle(i) of
rvsTable:
begin
Table := TRVTableItemInfo(RVData.GetItem(i));
for r := 0 to Table.RowCount-1 do
begin
for c := 0 to Table.ColCount-1 do
begin
if Table.Cells[r,c]<>nil then
begin
SetCellFieldData(Table.Cells[r,c].GetRVData);
end;
end;
end;
end;
rvsLabel:
if RVData.GetItemStyle(i) = rvsLabel then
begin
FieldName := PChar(RVData.GetItemTag(i));
if (IsFieldName(FieldName)) and (FieldName <> '') then
begin //Check if the field name is valid and there is data.
StyleNo := GetClosestTextStyleNo(RVData, i);
TRVLabelItemInfo(RVData.GetItem(i)).Text := GetFieldValueFromDatabase(FieldName);
TRVLabelItemInfo(RVData.GetItem(i)).TextStyleNo := StyleNo;
TRVLabelItemInfo(RVData.GetItem(i)).Changed;
RichViewEdit1.Modified := True;
end;
end;
end;
end;
end;
//Your solution to find the previous style or pass the default style if one does not exist. I left the last part out as you may want to have two items with different styles in the same cell and not have the first item have the second item's style.
function TForm3.GetClosestTextStyleNo(RVData: TCustomRVData; ItemNo: Integer) : Integer;
var i: Integer;
begin
Result := 0;
for i := ItemNo - 1 downto 0 do
if RVData.GetItemStyle(i) >= 0 then
begin
Result := RVData.GetItemStyle(i);
exit;
end;
end;
procedure TForm3.SetCellFieldData(RVData: TCustomRVData);
var i, StyleNo : Integer;
FieldName : String;
begin
for i := 0 to RVData.ItemCount - 1 do
begin
if RVData.GetItemStyle(i) = rvsLabel then
begin
FieldName := PChar(RVData.GetItemTag(i));
if (IsFieldName(FieldName)) and (FieldName <> '') then
begin
if RVData.ItemCount > 1 then
begin
if i > 0 then
begin
if (RVData.GetItemText(i - 1) = ' ') then
begin //If there are more than two items and the first is preceeded by a space.
StyleNo := GetClosestTextStyleNo(RVData, i);
TRVLabelItemInfo(RVData.GetItem(i)).Text := GetFieldValueFromDatabase(FieldName);
TRVLabelItemInfo(RVData.GetItem(i)).TextStyleNo := StyleNo;
TRVLabelItemInfo(RVData.GetItem(i)).Changed;
RichViewEdit1.Modified := True;
end;
end else
begin //More than one tag but no first space so set the default style
TRVLabelItemInfo(RVData.GetItem(i)).Text := GetFieldValueFromDatabase(FieldName);
TRVLabelItemInfo(RVData.GetItem(i)).TextStyleNo := 0;
TRVLabelItemInfo(RVData.GetItem(i)).Changed;
end;
end else
begin // One tag but no preceeding first space so set the default style
TRVLabelItemInfo(RVData.GetItem(i)).Text := GetFieldValueFromDatabase(FieldName);
TRVLabelItemInfo(RVData.GetItem(i)).TextStyleNo := 0;
TRVLabelItemInfo(RVData.GetItem(i)).Changed;
end;
end;
end;
end;
if (RVData.ItemCount > 1) and (RVData.GetItemText(0) = ' ') then
RVData.DeleteItems(0,1); //if the first item is a space holding the style delete it. If you needed extra spaces just add them in front of the tag in the template.
end;
It is working fine. I havent found any problems with it yet I''ll keep testing it.