MailMerge InsertHtml 遵循 Word-doc 对齐方式
MailMerge InsertHtml follow Word-doc alignment
我目前正在处理 MailMerge Word-doc。它部分填充了字符串,部分填充了 html(可以包含表格、图片、bold/italic/underlined 文本等)。与默认单词对齐方式相比,单词 doc 也具有自定义对齐方式(因此 left, top, right, bottom
的标尺类似于我的 MailMerge word-doc 中的 1.5, 0.3, 0.3, 0.3
,而单词默认值类似于 2.5, 2.5, 2.5, 2.5
.)
现在的问题是 InsertHtml
跳入(并且似乎遵循默认的单词对齐方式,而不是我们自定义的对齐方式),而不是按照单词中存在的静态文本和表格对齐-doc.
我知道 MailMerging 使用默认的 MS Word 函数来插入 html,所以问题可能在于该默认函数而不是 Apose 的 MailMerging。我只是想知道是否有人知道解决方案。
这是结果的可视化示例。我已经包含了标尺,其中 X
是在标尺上设置的用于对齐的位置。假设我们在 HTML 部分插入的文本是一些非常基本的文本,例如纯文本:"this is a test HTML text"。 Word-doc 模板如下所示:
+ . 2 . | X 1 ............................................... 17 . | . X . |
X *Start of a table*
. ...
. Value: | {{Value}}
. *End of the table*
.
. *A bold title*
.
. {{html_Text}}
.
. *Another bold title*
.
X
29
+
但是 MailMerging 后的结果是这样的:
+ . 2 . | X 1 ............................................... 17 . | . X . |
X *Start of a table*
. ...
. Value: | 2500
. *End of the table*
.
. *A bold title*
.
. this is a test HTML text
.
. *Another bold title*
.
X
29
+
html 文本错误地按照默认的 Word 标尺对齐,而不是该文档的自定义标尺。
(PS:我知道带括号 {{Something}}
的 MailMerging 比 <<Something>>
用得少,但两者的工作原理相同。有人质疑我们的 MailMerge 语法过去使用过,因此请注意。)
下面是我们.NET项目中的相关代码:
打印 DTO 对象:
public class OurObjectPrintDto
{
public OurObjectPrintDto(OurObject ob)
{
...
Value = ob.Value;
...
html_Text = ob.Text;
}
public string Value { get; private set; }
public string html_Text { get; private set; }
}
我们点击生成文档按钮时的方法:
[HttpGet]
public ActionResult Print(Guid id)
{
var ourObject = NhSession.GetByGuid<OurObject>(id);
var printData = new OutObjectPrintDto(ourObject);
var documentAsByteArray = _documentService.CreateMyObjectPrintAsBytes(printData);
return File(documentAsByteArray, "application/pdf");
}
CreateMyObjectPrintAsBytes
-方法:
public byte[] CreateMyObjectPrintAsBytes(MyObject printData)
{
return GenerateDocument("myobject.docx", printData);
}
private byte[] GenerateDocument(string fileName, object printData)
{
if (printData == null) throw new ArgumentNullException("printData");
var path = Path.Combine(_templatePath, fileName);
using (var fileStream = new File.OpenRead(path))
{
var dataSource = new DocumentDataSource(printData);
return DocumentConverter.GenerateDocument(fileStream, dataSource);
}
}
DocumentConvert.GenerateDocument
-方法:
public byte[] GenerateDocument(Stream template, DocumentDataSource dataSource)
{
var doc = new Document(template);
doc.MailMerge.UseNonMergeFields = true;
doc.MailMerge.CleanupOptions = MailMergeCleanupOption.RemoveContainingFields |
MailMergeCleanupOptions.RemoveUnusedFields |
MailMergeCleanupOptions.RemoveUnusedRegions |
MailMergeCleanupOptions.RemoveEmptyParagraphs;
doc.ResourceLoadingCallback = new ImageLoadingHandler();
// Support html MailMerge-fields
doc.MailMerge.FieldMergingCallback = new HandleMergeFieldInsertHtml();
doc.MailMerge.Execute(dataSource);
doc.MailMerge.ExecuteWithRegions((IMailMergeDataSourceRoot) dataSource);
doc.UpdateFields();
using (var memoryStream = new MemoryStream())
{
doc.Save(memoryStream, SaveFormat.Pdf);
return memoryStream.ToArray();
}
}
HandleMailMergeFieldInsertHtml
-class:
using Aspose.Words;
using Aspose.Words.Reporting;
namespace Sogyo.Util.Pdf
{
public class HandleMergeFieldInsertHtml : IFieldMergingCallback
{
// This is called when merge field is atually merged with data in the document
void IFieldMergingCallback.FieldMerging(FieldMergingArgs e)
{
// All merge field that expect HTML data should be marked with the prefix 'html_'
if (e.DocumentFieldName.StartsWith("html_") && e.FieldValue != null)
{
// Insert the text for this merge field as HTML data
var documentBuilder = new DocumentBuilder(e.Document);
documentBuilder.MoveToMergeField(e.DocumentFieldName);
documentBuilder.InsertHtml((string) e.FieldValue);
// The HTML text itself should not be inserted.
// We have already inserted it as an HTML.
e.Text = "";
}
}
void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs e)
{
}
}
}
我确实尝试在代码中设置 documentBuilder
的 .PageSetup.LeftMargin
来更改文档的标尺。这确实改变了文档的标尺对齐方式,但插入的 html 文本仍然以相同的量跳入,就好像它前面有一个制表符或其他东西一样..
好的,问题已解决。作为测试,我尝试将 out-put 临时更改为 .docx
而不是 .pdf
,这样我可以更好地查看选项卡等在转换后的文档中:
doc.Save(memoryStream, SaveFormat.Pdf);
// changed to
doc.Save(memoryStream, SaveFormat.Docx);
和
return File(documentAsByteArray, "application/pdf");
// changed to
return File(documentAsByteArray, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
当我打开转换后的 .docx
时,我很快发现了问题。它与 MailMerging 没有任何关系,但与文档本身的标尺有关。 Word-doc 标尺有灰色部分和 hourglass-kinda-thingy(我问题中的 X
)。
设置为:
而不是这个:
将我的 Word 文档中的 hourglass-thingy 和灰色部分相互对齐后,html 文本在 MailMerging 后也与其余部分正确对齐。
我目前正在处理 MailMerge Word-doc。它部分填充了字符串,部分填充了 html(可以包含表格、图片、bold/italic/underlined 文本等)。与默认单词对齐方式相比,单词 doc 也具有自定义对齐方式(因此 left, top, right, bottom
的标尺类似于我的 MailMerge word-doc 中的 1.5, 0.3, 0.3, 0.3
,而单词默认值类似于 2.5, 2.5, 2.5, 2.5
.)
现在的问题是 InsertHtml
跳入(并且似乎遵循默认的单词对齐方式,而不是我们自定义的对齐方式),而不是按照单词中存在的静态文本和表格对齐-doc.
我知道 MailMerging 使用默认的 MS Word 函数来插入 html,所以问题可能在于该默认函数而不是 Apose 的 MailMerging。我只是想知道是否有人知道解决方案。
这是结果的可视化示例。我已经包含了标尺,其中 X
是在标尺上设置的用于对齐的位置。假设我们在 HTML 部分插入的文本是一些非常基本的文本,例如纯文本:"this is a test HTML text"。 Word-doc 模板如下所示:
+ . 2 . | X 1 ............................................... 17 . | . X . |
X *Start of a table*
. ...
. Value: | {{Value}}
. *End of the table*
.
. *A bold title*
.
. {{html_Text}}
.
. *Another bold title*
.
X
29
+
但是 MailMerging 后的结果是这样的:
+ . 2 . | X 1 ............................................... 17 . | . X . |
X *Start of a table*
. ...
. Value: | 2500
. *End of the table*
.
. *A bold title*
.
. this is a test HTML text
.
. *Another bold title*
.
X
29
+
html 文本错误地按照默认的 Word 标尺对齐,而不是该文档的自定义标尺。
(PS:我知道带括号 {{Something}}
的 MailMerging 比 <<Something>>
用得少,但两者的工作原理相同。有人质疑我们的 MailMerge 语法过去使用过,因此请注意。)
下面是我们.NET项目中的相关代码:
打印 DTO 对象:
public class OurObjectPrintDto
{
public OurObjectPrintDto(OurObject ob)
{
...
Value = ob.Value;
...
html_Text = ob.Text;
}
public string Value { get; private set; }
public string html_Text { get; private set; }
}
我们点击生成文档按钮时的方法:
[HttpGet]
public ActionResult Print(Guid id)
{
var ourObject = NhSession.GetByGuid<OurObject>(id);
var printData = new OutObjectPrintDto(ourObject);
var documentAsByteArray = _documentService.CreateMyObjectPrintAsBytes(printData);
return File(documentAsByteArray, "application/pdf");
}
CreateMyObjectPrintAsBytes
-方法:
public byte[] CreateMyObjectPrintAsBytes(MyObject printData)
{
return GenerateDocument("myobject.docx", printData);
}
private byte[] GenerateDocument(string fileName, object printData)
{
if (printData == null) throw new ArgumentNullException("printData");
var path = Path.Combine(_templatePath, fileName);
using (var fileStream = new File.OpenRead(path))
{
var dataSource = new DocumentDataSource(printData);
return DocumentConverter.GenerateDocument(fileStream, dataSource);
}
}
DocumentConvert.GenerateDocument
-方法:
public byte[] GenerateDocument(Stream template, DocumentDataSource dataSource)
{
var doc = new Document(template);
doc.MailMerge.UseNonMergeFields = true;
doc.MailMerge.CleanupOptions = MailMergeCleanupOption.RemoveContainingFields |
MailMergeCleanupOptions.RemoveUnusedFields |
MailMergeCleanupOptions.RemoveUnusedRegions |
MailMergeCleanupOptions.RemoveEmptyParagraphs;
doc.ResourceLoadingCallback = new ImageLoadingHandler();
// Support html MailMerge-fields
doc.MailMerge.FieldMergingCallback = new HandleMergeFieldInsertHtml();
doc.MailMerge.Execute(dataSource);
doc.MailMerge.ExecuteWithRegions((IMailMergeDataSourceRoot) dataSource);
doc.UpdateFields();
using (var memoryStream = new MemoryStream())
{
doc.Save(memoryStream, SaveFormat.Pdf);
return memoryStream.ToArray();
}
}
HandleMailMergeFieldInsertHtml
-class:
using Aspose.Words;
using Aspose.Words.Reporting;
namespace Sogyo.Util.Pdf
{
public class HandleMergeFieldInsertHtml : IFieldMergingCallback
{
// This is called when merge field is atually merged with data in the document
void IFieldMergingCallback.FieldMerging(FieldMergingArgs e)
{
// All merge field that expect HTML data should be marked with the prefix 'html_'
if (e.DocumentFieldName.StartsWith("html_") && e.FieldValue != null)
{
// Insert the text for this merge field as HTML data
var documentBuilder = new DocumentBuilder(e.Document);
documentBuilder.MoveToMergeField(e.DocumentFieldName);
documentBuilder.InsertHtml((string) e.FieldValue);
// The HTML text itself should not be inserted.
// We have already inserted it as an HTML.
e.Text = "";
}
}
void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs e)
{
}
}
}
我确实尝试在代码中设置 documentBuilder
的 .PageSetup.LeftMargin
来更改文档的标尺。这确实改变了文档的标尺对齐方式,但插入的 html 文本仍然以相同的量跳入,就好像它前面有一个制表符或其他东西一样..
好的,问题已解决。作为测试,我尝试将 out-put 临时更改为 .docx
而不是 .pdf
,这样我可以更好地查看选项卡等在转换后的文档中:
doc.Save(memoryStream, SaveFormat.Pdf);
// changed to
doc.Save(memoryStream, SaveFormat.Docx);
和
return File(documentAsByteArray, "application/pdf");
// changed to
return File(documentAsByteArray, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
当我打开转换后的 .docx
时,我很快发现了问题。它与 MailMerging 没有任何关系,但与文档本身的标尺有关。 Word-doc 标尺有灰色部分和 hourglass-kinda-thingy(我问题中的 X
)。
设置为:
而不是这个:
将我的 Word 文档中的 hourglass-thingy 和灰色部分相互对齐后,html 文本在 MailMerging 后也与其余部分正确对齐。