QMacros 2017年9月18日提交的版本支持了迭代器,以重复替换某一部分内容。
迭代器的声明:
IQMacroIterator = interface
['{3DB5D84F-0539-4C10-9476-E6B71D3099DE}']
// 开始替换
procedure BeginReplace(AMacro: TQMacroItem);
// 判断是否还有要处理的数据
function HasNext: Boolean;
// 执行一次替换
function Replace: QStringW;
// 结束替换
procedure EndReplace;
// 获取当前活动的迭代器序号
function GetItemIndex: Integer;
end;
好吧,这是一个接口,这就意味着,我们绑定某个宏到这个迭代器之前,需要先实现一个迭代器。我们可以继承自 TQMacroIterator 实现一个自带的迭代器绑定,从而实现自己的替换规则。要实现自己的迭代器,可以看一下默认的 TQMacroDataSetIterator 实现来参考一下。
QMacros 内置了数据集的迭代器,假设你的数据集的 Name 为 adsData,则 adsData.@Rows 宏对应的就是一个迭代器,这个宏包含三个参数:
- 要替换的模板,一个字符串类型的参数,转义语法遵守 C/Java 语法;
- 模板中宏的起始字符标志字符串
- 模板中宏的结束字符标志字符串
我们来看一个示例:
procedure TForm1.Button1Click(Sender: TObject);
const
STableTemplate: QStringW = '<html><head><title><%Title%></title></head>' + //
'<body>这是一个表格<table border="1" cellspacing="0" cellpadding="0" bordercolor="#000000" style="BORDER-COLLAPSE: collapse">'
+ //
'<th><tr><td>记录号</td><td>序号</td><td>编号</td><td>姓名</td></tr></th>' + //
'%adsData.@Rows("<tr><td>%adsData.@RecNo%</td><td>%adsData.@Rows.@Index%<td>%Id%</td><td>%Name%</td></tr>","%","%")%'
+ //
'</table></body>';
var
AMacros: TQMacroManager;
AHtmlFile, AHtmlText, ATag: String;
begin
AMacros := TQMacroManager.Create;
try
AMacros.Push(adsData, '');
AMacros.Push('Title', 'QMacros HTML Tag 替换');
AHtmlText := AMacros.Replace(STableTemplate, '%', '%', MRF_PARSE_PARAMS);
AHtmlFile := ExtractFilePath(Application.ExeName) + 'index.html';
SaveTextW(AHtmlFile, AHtmlText);
WebBrowser1.Navigate('file:///' + StringReplaceW(AHtmlFile, '\', '/',
[rfReplaceAll]));
AMacros.Pop(adsData, '');
finally
FreeAndNil(AMacros);
end;
end;在这个示例中,STableTemplate 是一个简单的HTML模板,我们需要将数据集adsData的内容,输出为一个HTML的表格,那么核心就在
%adsData.@Rows(“<tr><td>%adsData.@RecNo%</td><td>%adsData.@Rows.@Index%<td>%Id%</td><td>%Name%</td></tr>”,”%”,”%”)%
这一行:adsData.@Rows 在我们调用 AMacros.Push(adsData,”) 时,被自动入栈为一个迭代器,当我们调用 AMacros.Replace 来执行替换时,它会从第一条记录循环到最后一条记录,按照第一个参数指定的模板循环输出内容,如果其中包含宏定义,则会替换成相应的宏定义。
我们来看一下这段代码的执行结果:
好吧,就说到这里。具体的代码请自行 SVN/GIT 检出。

