📄 mmmainfrm.cpp
字号:
/*==============================================================================
{
Mail merge application: part 2 - displaying processed template.
How it works:
- RVStyle2 has two predefined styles (the same as in the template editor;
1th text style is reserved for fields).
- RichView1 and RichView2 are linked to the same RVStyle (RVStyle2)
- Template is loaded in RichView1 (styles can be added dynamically in RVStyle2)
- RichView1 is scanned for fields. When field is found, it is deleted,
and its value is inserted in its place:
* field value is loaded in invisible RichView2 (styles can be added in RVStyle2)
* contents of RichView2 is inserted in the proper place of RichView1.
}
==============================================================================*/
#include <vcl.h>
#pragma hdrstop
#include "MMMainFrm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "RichView"
#pragma link "RVScroll"
#pragma link "RVStyle"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
// Loading template with fields
RichView1->LoadRVF(ExtractFilePath(Application->ExeName)+"Template.rvf");
// RVData->InsertFromStream() (we will call it later) does not support
// style merging. So changing mode to style ignoring:
RichView1->RVFParaStylesReadMode = rvf_sIgnore;
RichView1->RVFTextStylesReadMode = rvf_sIgnore;
// Replace styles with values
ReplaceFields(RichView1->RVData);
RichView1->Format();
}
//---------------------------------------------------------------------------
void TForm1::ReplaceFields(TCustomRVFormattedData* RVData)
{
TColor Dummy1 = clNone;
TRVBackground * Dummy2 = NULL;
TRVLayoutInfo * Dummy3 = NULL;
for (int i=RVData->ItemCount-1; i>=0; i--)
{
switch (RVData->GetItemStyle(i))
{
case 1: // the first text style is used for fields
{
// storing parameters of deleted items
int ParaNo = RVData->GetItemPara(i);
bool BR = RVData->GetItem(i)->BR;
bool ContinuePara = RVData->GetItem(i)->SameAsPrev;
// loading field value in the stream
TMemoryStream* Stream;
LoadData(RVData->GetItemTextA(i), Stream);
if (Stream)
{
// deleting the field code
RVData->DeleteItems(i,1);
// inserting the field value
RVData->InsertRVFFromStream(Stream, i, Dummy1, Dummy2, Dummy3, false);
// applying stored parameters to the inserted items
for (int j = i; j<RVData->ItemCount; j++)
{
if (i==j)
{
RVData->GetItem(j)->SameAsPrev = ContinuePara;
if (BR)
RVData->GetItem(j)->BR = true;
}
if (j>i && RVData->IsParaStart(j))
break;
RVData->GetItem(j)->ParaNo = ParaNo;
}
delete Stream;
}
break;
}
case rvsTable:
{
// recursive call for table cells
TRVTableItemInfo* table = (TRVTableItemInfo*)(RVData->GetItem(i));
for (int r=0; r<table->Rows->Count; r++)
for (int c=0; c<table->Rows->Items[r]->Count; c++)
if (table->Cells[r][c])
ReplaceFields(table->Cells[r][c]);
break;
}
}
}
RVData->Normalize();
}
//---------------------------------------------------------------------------
// Loading field code
void TForm1::LoadData(const AnsiString Code, TMemoryStream* &Stream)
{
TLocateOptions SearchOptions;
if (! Table1->Locate("Code", Code, SearchOptions))
return;
Stream = new TMemoryStream;
((TBlobField*)(Table1->FieldByName("Data")))->SaveToStream(Stream);
Stream->Position = 0;
RichView2->Clear();
RichView2->InsertRVFFromStream(Stream, 0); // inserting will merge styles;
// RichView1 and RichView2 have the same collections of styles
Stream->Clear();
RichView2->SaveRVFToStream(Stream, false);
Stream->Position = 0;
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -