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

Code: Select all

RVData.GetItem(i).StyleNo := 0;
The tags are not replaced.

Posted: Mon Jan 24, 2011 5:11 pm
by Sergey Tkachenko
1) The line

Code: Select all

RVData.GetItem(i).StyleNo := 0
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 richview@gmail.com 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.