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 检出。