Aspose.words转换带有页眉页脚的文档,转换出来的pdf排版不正确

使用aspose.words将一个带有页眉页脚的文档转为pdf,版式是不对的和word不一致,这是转换的代码:

        public static void ConvertWord2Pdf(string documentFileName, string SavePdfName, string tempSaveDocxPath, Aspose.Words.Saving.PdfCompliance PdfComplanceOption, Aspose.Words.Settings.MsWordVersion OptiMizMswVersion, bool UpdateField,
            Aspose.Words.Saving.ColorMode SavePdfColorMode)
        {
            string DocumentName, SaveDocxName;

            //设置加载word文档的时候参数
            Aspose.Words.Loading.LoadOptions TempDocuemntLoadOption = new Aspose.Words.Loading.LoadOptions()
            {
                ConvertMetafilesToPng = false,
                MswVersion = OptiMizMswVersion,
            };

            //设置PDF保存参数
            Aspose.Words.Saving.PdfSaveOptions TempPdfaveOption = new Aspose.Words.Saving.PdfSaveOptions()
            {
                FontEmbeddingMode = Aspose.Words.Saving.PdfFontEmbeddingMode.EmbedAll,
                ColorMode = SavePdfColorMode,
                ImageColorSpaceExportMode = Aspose.Words.Saving.PdfImageColorSpaceExportMode.Auto,
                ImageCompression = Aspose.Words.Saving.PdfImageCompression.Auto,
                PageMode = Aspose.Words.Saving.PdfPageMode.UseOutlines,
                ZoomBehavior = Aspose.Words.Saving.PdfZoomBehavior.None,
                SaveFormat = Aspose.Words.SaveFormat.Pdf,
                UseHighQualityRendering = true,
                UseAntiAliasing = true,
                PreblendImages = true,
                JpegQuality = 100,
                Compliance = PdfComplanceOption,
                ExportGeneratorName = false,
                UpdateFields = UpdateField,
            };

            //设置PDF保存带word中的目录
            TempPdfaveOption.OutlineOptions.DefaultBookmarksOutlineLevel = 0;
            TempPdfaveOption.OutlineOptions.CreateMissingOutlineLevels = false;
            TempPdfaveOption.OutlineOptions.ExpandedOutlineLevels = 3;
            TempPdfaveOption.OutlineOptions.HeadingsOutlineLevels = 9;
            TempPdfaveOption.HeaderFooterBookmarksExportMode = Aspose.Words.Saving.HeaderFooterBookmarksExportMode.All;


            //设置Docx保存参数
            Aspose.Words.Saving.OoxmlSaveOptions TempDocxSaveOption = new Aspose.Words.Saving.OoxmlSaveOptions()
            {
                Compliance = Aspose.Words.Saving.OoxmlCompliance.Iso29500_2008_Transitional,
                SaveFormat = Aspose.Words.SaveFormat.Docx,
                KeepLegacyControlChars = true,
                UpdateFields = UpdateField,
            };

            Aspose.Words.Document TempDocument = new Aspose.Words.Document(documentFileName,
                                                                           TempDocuemntLoadOption)
            {
                RemovePersonalInformation = true,
            };

            TempDocument.CompatibilityOptions.OptimizeFor(OptiMizMswVersion);
            TempDocument.CompatibilityOptions.BalanceSingleByteDoubleByteWidth = true;//区分全角和半角字符


            DocumentName = System.IO.Path.GetFileNameWithoutExtension(documentFileName);

            SaveDocxName = System.IO.Path.Combine(tempSaveDocxPath, DocumentName + ".docx");


            TempDocument.Save(SaveDocxName, TempDocxSaveOption);

            Aspose.Words.Document TempDocxDocument = new Aspose.Words.Document(SaveDocxName, TempDocuemntLoadOption);

            TempDocxDocument.Save(SavePdfName, TempPdfaveOption);
        }

这是word文档和转换后的pdf文件:

files.zip (111.7 KB)

是不是word里面有什么设置没调对,还是有什么参数可以调整这种情况?我测试发现,如果删除word文档的页眉页脚后的样式,就和转换出来的pdf样式是一样的。

@jidesheng, 您能否附上由 Microsoft Word 和 Aspose.Words 创建的 PDF 文件,以便我可以比较它们并找出差异?

test.zip (274.4 KB)

压缩文件中,aspose.pdf文件是aspose.words转换的pdf文档,word2pdf.pdf文件是word另存为pdf保存的pdf文档,麻烦看一下,比较明显的就是第三部分和第四部分那块有明显区别。

@jidesheng, 在您的 PDF 文件中使用不同的字体,这可能是您获得不同文档布局的原因:

word2pdf.pdf

FangSong_GB2312 Regular Version 2.00
Malgun Gothic Semilight Regular Version 6.68
Microsoft YaHei Regular Version 6.30

aspose.pdf

FangSong_GB2312 Regular Version 2.00
KaiTi Regular Version 5.01
Times New Roman Regular Version 7.03

正文使用 FangSong_GB2312 字体,页眉使用 KaiTi 字体。 Microsoft Word 似乎无法找到 KaiTi 字体,并用其他字体替代。

请尝试安装缺失的字体并检查问题是否消失。

安装楷体后的文件(aspose.words转换).pdf (105.5 KB)
我已经在系统中安装了缺失的字体,这是aspose.words转换的pdf,问题好像还是存在,应该不是出现在字体上,你可以尝试将源word中的页眉页脚删除,将会和aspose.words转换的pdf一样的排版样式,但是我不清楚这是aspose.words的问题,还是word的兼容性设置没有调整正确的原因。

@jidesheng, 您使用什么版本的 Aspose.Words?

这些是我的计算机上由 Aspose.Words 和 Microsoft Word 2019 创建的 PDF 文件:

测试.word2019.pdf (188.5 KB)
测试.aspose.words.23.11.pdf (108.4 KB)

它们几乎完全相同。 他们使用同一组字体:

FangSong Regular Version 5.01
KaiTi Regular Version 5.01
KaiTi Regular Version 5.01

我使用了最少的代码来转换为 PDF:

Document doc = new ("测试.doc");
doc.Save("测试.aspose.words.23.11.pdf");

你能用这个最少的代码产生类似的结果吗?

Screenshot_20231120_213259.jpg (160.7 KB)

正确的pdf文档布局应该是如图所示,word文档的排版也是这样的,你给我的文件中,转换后“第四部分”标题下方应该是分页符,但是文件中是下一航的文字,没有正确按照原文档得布局来转换,或许你可以给我提供一下您电脑上打开我提供的测试word文档得截图,我确认一下是不是我们得到的文档布局是不一样的。

@jidesheng, 根据系统区域设置,Microsoft Word 可以为此文档生成不同的布局。 我附上了当系统区域设置为英语和中文时由 Microsoft Word 生成的 PDF 文件。

测试.word2019.Chinese.Locale.pdf (183.2 KB)
测试.word2019.English.Locale.pdf (188.5 KB)

Aspose.Words 还无法为中文语言环境生成精确的布局。 我在我们的内部问题跟踪系统中记录了一张新票证,并将根据 免费支持政策 中提到的条款提供它们的修复:

Issue ID(s): WORDSNET-26247

如果您需要优先支持以及直接联系我们的付费支持管理团队,您可以获得 付费支持服务

首先非常感谢这么晚了还在处理问题

其次我发现有个问题,提供的两份pdf,Chinese那份是期望的样式,也是和word文档布局一致得;English那份是我使用aspose进行转换得到的样式。

请问一下,这是你们那边操作系统在区域设置英文和中文时不同的转换结果吗,我是不是可以理解为,aspose在转换的时候,是按照区域语言为英文的设置对文档进行转换的?

@jidesheng, 我安装了英语设置的 Windows。 为了使 Microsoft Word 的行为与在具有中文设置的 Windows 上运行一样,我更改了 2 个设置:

  1. Windows中的系统区域设置应更改为 Chinese (Simplified, China)
  2. Microsoft Word默认编辑语言应更改为 Chinese (China)

在 Aspose.Words 中,无论系统区域设置如何,默认情况下都会启用一些中文特定功能。 当您将默认语言设置为中文时,某些功能将启用,如下面的代码示例所示:

LoadOptions opts = new LoadOptions();
opts.LanguagePreferences.DefaultEditingLanguage = EditingLanguage.ChinesePRC;

Document doc = new Document("in.docx", opts);
doc.Save("out.pdf");

因此,默认情况下,如果不指定 LoadOptions,Aspose.Words 将像在英文环境下的 Word 一样生成 PDF 文件,并启用一些中文功能。

谢谢,我大概了解了,有一个问题请问一下,为了避免这种情况,我想让加载的word文档找不到字体的时候,默认用Sim Sun字体替代,这个在aspose.words中可以实现吗,我没在api手册中找到相关内容。

@jidesheng, 我认为这可以通过 FontSettings 和相关类实现。 您可以在我们的文档中阅读有关这些类的更多信息:

好的,我大概了解了。

我刚才又测试了几次,我发现一个事情,当我把Fangsong_GB2312和KATI_GB2312这两个字体从系统中删除后,我在word中查看他们就是没有字体的样式,但是当我把他们用aspose.words转换为pdf的时候,我发现在pdf文件中,他们好像是被嵌入的字体,但是我系统中并没有这两个字体,而且在代码中我也删除了和字体有关的设置,为什么会这样呢?

Aspose是不是会自动搜索系统字体库中的字体,并根据文档设置的字体选取相似字体应用?

比如我的文档正文用的是FangSong_GB2312,但是我的系统中只有FangSong字体,那么我将文档转换为PDF的时候,Aspose.words是不是会给正文自动应用FangSong字体?而不是内部设置的默认替换字体?
如果是的话,可以通过代码来控制这个功能的启用与否吗?

@jidesheng, 是的,Aspose会自动在系统字体库中搜索字体,并根据文档中设置的字体选择相似的字体来应用。 对于 FangSong_GB2312 和 FangSong 以及 KaiTi_GB2312 和 KaiTi,Aspose.Words 有一个硬编码的替换规则来模拟 Microsoft Word 的行为。 我将与负责的开发人员讨论是否可以禁用这些规则并让您知道。

谢谢,我发现对于word来说,虽然他会在界面上显示当前字体为FangSong_GB2312,但是实际显示的字体形状可能是SimSun等字体,但是我并不清楚,因为即使你的系统中没有Fangsong_GB2312字体,word也不会帮你改成FangSong字体(如果FangSong字体存在),包括在转换为PDF的时候,word也不会自动替换为Fangsong字体,而是保持原来的SimSun或者其他字体,Aspose在转换的时候就会执行相似替换操作。

@jidesheng, 根据系统区域设置,Microsoft Word 会对文档执行不同的字体替换。
如果系统区域设置为英语,则 Word 会将 FangSong_GB2312 替换为 FangSong,将 KaiTi_GB2312 替换为 KaiTi。 因此,Aspose.Words 在这种情况下执行相同的替换。

如果系统区域设置为中文,Word 将 FangSong_GB2312 替换为 Microsoft YaHei,将 KaiTi_GB2312 替换为 Malgun Gothic Semilight/Microsoft JhengHei/MS Gothic。 Aspose.Words 中未实现此行为。

这可能仅适用于我的计算机,因为您的计算机可能有不同的字体集。

也就是说,当前版本的Aspose.Words(23.11)还不支持word在中文下对一些未存在的字体进行替换操作?如果是这样的话,Aspose.Words将来会全面支持中文环境下对未存在的字体进行和word一样的替换操作吗?现在的方案我能想到的有两个,一个是自己系统拥有某份文档内的全部字体;第二个就是aspose可以获取到文档内哪些字体是系统中存在还是不存在的吗?

@jidesheng, 是的,当系统语言环境为中文时,Aspose.Words 不支持 Microsoft Word 执行的字体替换。 我在我们的内部问题跟踪系统中开了一张新票。我们并将根据 免费支持政策 中提到的条款提供它们的修复:

Issue ID(s): WORDSNET-26254

关于你的第二个解决方案。

如果文档是使用 Microsoft Word 创建的,则可以使用 Document.FontInfos 属性来获取文档中使用的字体列表。
您还可以实现 IWarningCallback 以在 Aspose.Words 找不到文档中指定的特定字体并替换它时收到通知。 将文档渲染为 PDF 时调用此回调。

您还可以通过迭代可用字体源来获取所有可用字体的列表,并列出这些源提供的字体。 例如,如果您没有指定额外的字体源,则可以使用以下代码来获取可用的字体:

FontSettings settings = FontSettings.DefaultInstance;
foreach (FontSourceBase fs in settings.GetFontsSources())
{
    foreach (PhysicalFontInfo info in fs.GetAvailableFonts())
    {
        Console.WriteLine(info.FullFontName);
    }
}

我看了几遍关于字体替换部分的文档,但是好像没有成功的替换过字体,所有想再请问下几个问题。

我根据文档中的方法,我对字体替换部分做了如下设置:

            AspWordsWarningCallBack AspCallBack = new AspWordsWarningCallBack();

            Aspose.Words.Fonts.FontSettings TempFontSettings = new Aspose.Words.Fonts.FontSettings();
            TempFontSettings.SubstitutionSettings.DefaultFontSubstitution.Enabled = true;
            TempFontSettings.SubstitutionSettings.TableSubstitution.Enabled = false;
            TempFontSettings.SubstitutionSettings.FontInfoSubstitution.Enabled = false;
            TempFontSettings.SubstitutionSettings.FontConfigSubstitution.Enabled = false;
            TempFontSettings.SubstitutionSettings.FontNameSubstitution.Enabled = false;
            TempFontSettings.SubstitutionSettings.DefaultFontSubstitution.DefaultFontName = "SimSun";


            //TempDocuemntLoadOption.FontSettings = TempFontSettings;

AspCallBack 就是我的iwarningcallback的实现,里面只有简单的输出信息。

            Aspose.Words.Document TempDocxDocument = new Aspose.Words.Document(SaveDocxName, TempDocuemntLoadOption);

            TempDocxDocument.WarningCallback = AspCallBack;
            TempDocxDocument.FontSettings = TempFontSettings;
            TempDocxDocument.LayoutOptions.KeepOriginalFontMetrics = true;

            TempDocxDocument.FontInfos.ToList().ForEach(x => Debug.WriteLine(x.Name));

            TempDocxDocument.Save(SavePdfName, TempPdfaveOption);

接着我根据文档配置callback和设置字体替换,但是输出信息提示如下:

Font '楷体_GB2312' has not been found. Using 'Malgun Gothic Semilight' font instead. Reason: alternative name from document.

我期望的是在确实找不到某个字体后,默认使用SimSun字体来替换(也就是宋体),但是给出的warning好像还是用了MalGun来替换的,同时我希望的也是aspose直接忽略系统中相同名称的字体,比如“楷体_GB2312:没有在系统中搜索到以后,就算搜索到了”楷体“字体,也不帮我执行替换,而是直接替换为SimSun;这一点我知道应该是你之前提过的Aspose内部执行的硬编码替换。

所以我想确定一下,替换字体这个操作,有办法实现我说的,设置规则为使用SimSun来替换吗(在系统中确实没有文档中的字体或者相似字体的时候)?如果可以的话,正确的代码应该是什么样子的;还是说,替换字体无法实现,我只能使用warningcallback简单的输出字体替换的信息?