您好,我将Aspose.Words 18.11版本升级到22.10版本遇到了问题!

感谢您的查看和帮助!

18.11版本正常输出:
0003-012-0739.docx (11.5 KB)
0003-012-0740.docx (11.3 KB)

22.10版本错误输出:
0003-012-0739.docx (13.0 KB)
0003-012-0740.docx (12.7 KB)

这是我为您整理的整个项目,您需要下载下来启动它,代码量很少。
AsposeToWordTableTest.7z (5.2 MB)

@fhn123456 您应该将以下代码移动到使用 DocumentBuilder 完成构建表的位置,然后再添加空行:

builder.EndTable();

//自动调整
table.AutoFit(Aspose.Words.Tables.AutoFitBehavior.FixedColumnWidths);
table.AllowAutoFit = false;

非常感谢您的帮助,我将代码移动到创建空行前,确实解决了我的问题!

对于结束表格我有一个疑问?

1,builder.EndTable();这行代码我应该放到,创建空行前还是table.LastRow.Remove();之前还是之后?

2,Aspose.Words.Layout.LayoutCollector collector = new Aspose.Words.Layout.LayoutCollector(doc);

API:collector.GetEndPageIndex(table.NextSibling);
API:collector.GetEndPageIndex(table.LastRow);

这两个有什么区别?

A post was split to a new topic: Aspose.PDF升级之后使用不正常!

@fhn123456

  1. 在使用 DocumentBuilder 完成表构建之后,您应该放置 builder.EndTable()。 table.LastRow.Remove() 这段代码与 DocumentBuilder 无关,在这里您直接使用 DOM。

  2. 第一个返回表后段落的页码,第二个返回最后一个表行的页码。 请注意,在 MS Word 文档中,表格不能是最后一个节点,表格后面总是有一段。

好的,感谢您的回复和帮助!
我还有一个疑问,为什么我使用Aspose.Words.Layout.LayoutCollector,有时候会计算错误,数据只有一页,添加空行数应该是3行,但它添加了5行空行,导致table.LastRow.Remove();删除了一行,我在想是不是LayoutCollector更新不及时引起的多加行数。

我查看了API文档,发现有以下代码,但我不知道如何使用它们!
collector.Clear();
doc.UpdatePageLayout();

错误输出:错误输出.jpg (29.9 KB)

我向您提供测试文件Excel:测试文件.zip (9.7 KB)

@fhn123456 发生此问题的原因可能是原始文档中使用的字体在执行文档处理的环境中不可用。 要构建文档布局,Aspose.Words 需要文档中使用的字体。 字体被替换 如果 Aspose.Words 找不到文档中使用的字体。 这可能会导致字体不匹配和文档布局差异,从而返回不正确的页码。 您可以实施 IWarningCallback 以在执行字体替换时收到通知。

非常感谢您的回复和帮助!

我按照API指引完成了下面的代码,发现第二页的空白行更多了,所以您的猜想应该是正确的,我该如何使用它,您能否在我发您的项目上做出修改或者将代码放到回复中,万分感谢您!
错误的输出.jpg (26.4 KB)

/// <summary>
/// Aspose.doc 生成卷内表格
/// </summary>
public static void AsposeToWordTableOne(Aspose.Words.Document doc, string dhAjH)
{

    //Aspose.Words.Document doc = new Aspose.Words.Document();
    Aspose.Words.DocumentBuilder builder = new Aspose.Words.DocumentBuilder(doc);
    //设置字体
    builder.Font.Name = "SimSun";

    FontSubstitutionWarningCollector callback = new FontSubstitutionWarningCollector();
    doc.WarningCallback = callback;

    // 存储当前字体源集合,这将是每个文档的默认字体源
    // 我们没有指定不同的字体源。
    Aspose.Words.Fonts.FontSourceBase[] originalFontSources = Aspose.Words.Fonts.FontSettings.DefaultInstance.GetFontsSources();

    // 出于测试目的,我们将 Aspose.Words 设置为仅在不存在的文件夹中查找字体。
    Aspose.Words.Fonts.FontSettings.DefaultInstance.SetFontsFolder(string.Empty, false);

    ............................................................................

    //保存文档  
    doc.Save(jnMlPath);

    //table.Rows.Clear();
    //table.ChildNodes.Clear();
    //doc = null;


    Aspose.Words.Fonts.FontSettings.DefaultInstance.SetFontsSources(originalFontSources);

    bool cc = callback.FontSubstitutionWarnings[0].Description
        .Equals(
            "Font 'Times New Roman' has not been found. Using 'Fanwood' font instead. Reason: first available font.");

@fhn123456 当使用默认字体源时,IWarningCallback 是否会返回任何关于字体替换的警告? 使用这些警告,您可以检测丢失的字体并安装它们或在单独的文件夹中提供。

1,这段代码告诉我:
string cc1 = callback.FontSubstitutionWarnings[0].Description;

Font ‘宋体’ has not been found. Using ‘Fanwood’ font instead. Reason: first available font.

错误:

2,但是我的windows11 已经安装了“宋体”,如下图:

3,当我使用
Assert.True(callback.FontSubstitutionWarnings[0].Description
.Equals(
“Font ‘Times New Roman’ has not been found. Using ‘Fanwood’ font instead. Reason: first available font.”));

报错信息:
当前上下文中不存在名称“Assert”

示例3,解决了,我没有Microsoft.VisualStudio.TestTools.UnitTesting;

当我指定Fonts文件夹,发现字体没有生效!

// 从包含字体文件的文件夹创建字体源。
Aspose.Words.Fonts.FolderFontSource folderFontSource = new Aspose.Words.Fonts.FolderFontSource(@"C:\Windows\Fonts", false, 1);

Aspose.Words.DocumentBuilder builder = new Aspose.Words.DocumentBuilder(doc);
//设置字体
builder.Font.Name = "SimSun";


doc.FontSettings = new Aspose.Words.Fonts.FontSettings();
doc.FontSettings.SetFontsSources(new Aspose.Words.Fonts.FontSourceBase[] { folderFontSource });

string cc = folderFontSource.FolderPath;

Assert.AreEqual(@"C:\Windows\Fonts", folderFontSource.FolderPath);
Assert.AreEqual(false, folderFontSource.ScanSubfolders);
Assert.AreEqual(Aspose.Words.Fonts.FontSourceType.FontsFolder, folderFontSource.Type);
Assert.AreEqual(1, folderFontSource.Priority);

bool cc5 = folderFontSource.ScanSubfolders;



FontSubstitutionWarningCollector callback = new FontSubstitutionWarningCollector();
doc.WarningCallback = callback;
// 存储当前字体源集合,这将是每个文档的默认字体源
// 我们没有指定不同的字体源。
Aspose.Words.Fonts.FontSourceBase[] originalFontSources = Aspose.Words.Fonts.FontSettings.DefaultInstance.GetFontsSources();
// 出于测试目的,我们将 Aspose.Words 设置为仅在不存在的文件夹中查找字体。 @"C:\Windows\Fonts"  string.Empty
Aspose.Words.Fonts.FontSettings.DefaultInstance.SetFontsFolder(@"C:\Windows\Fonts", true);



Aspose.Words.Fonts.FontSettings.DefaultInstance.SetFontsSources(originalFontSources);


// Assert.IsTrue(callback.FontSubstitutionWarnings[0].Description
// .Equals(
//"Font 'Times New Roman' has not been found. Using 'Fanwood' font instead. Reason: first available font."));

string cc1 = callback.FontSubstitutionWarnings[0].Description;

bool cc6 = callback.FontSubstitutionWarnings[0].Description.Equals("Font 'Times New Roman' has not been found. Using 'Fanwood' font instead. Reason: first available font.");

@fhn123456 感谢您提供更多信息。 当 Aspose.Words 没有其他字体可用时,Fanwood 字体被用作最后的字体。 此字体嵌入到 Aspose.Words dll 中。 在您的代码中,您指定了一个空/不存在的文件夹作为字体源,这就是 Aspose.Words 使用 Fanwood 字体的原因。
请尝试使用默认字体源,即根本不要指定额外的字体设置,并检查 Aspose.Words 是否警告字体替换。
我之前已经在我这边测试了你的代码,并且空行已正确添加到表中。

感谢您的回复和帮助!

  • 您能否贴出您的代码供我参考,我想查看您使用的是否和你一致,非常感谢您!

  • Aspose.Words默认字体是Times New Roman吗?

1,我使用下面的代码可以实现,请您检查是否规范,SimSun替换掉Times New Roman字体!
Font ‘Times New Roman’ has not been found. Using ‘SimSun’ font instead. Reason: font info substitution.

/// <summary>
/// 设置字体
/// </summary>
public static Aspose.Words.Document AsposeWordFonts(Aspose.Words.Document doc)
{
    ////可用 指定字体      https://reference.aspose.com/words/zh/net/aspose.words.fonts/
    //Aspose.Words.Fonts.FileFontSource fileFontSource = new Aspose.Words.Fonts.FileFontSource(@"E:\workspace\1_20220606\home_tool\HomeTool\Fonts\simsun.ttc", 0);
    ////可用    设置默认字体名称并启用字体替换。
    //doc.FontSettings = new Aspose.Words.Fonts.FontSettings();
    //doc.FontSettings.SetFontsSources(new Aspose.Words.Fonts.FontSourceBase[] { fileFontSource });
    //string cc2 = fileFontSource.FilePath;

    //可用
    string FontsDir = @"E:\workspace\1_20220606\home_tool\HomeTool\Fonts";
    ////从包含字体文件的文件夹创建字体源。
    //Aspose.Words.Fonts.FolderFontSource folderFontSource = new Aspose.Words.Fonts.FolderFontSource(FontsDir, false, 1);
    //doc.FontSettings = new Aspose.Words.Fonts.FontSettings();
    //doc.FontSettings.SetFontsSources(new Aspose.Words.Fonts.FontSourceBase[] { folderFontSource });
    //string cc = folderFontSource.FolderPath;


    //可用 指定字体文件夹
    //Aspose.Words.Fonts.FontSourceBase[] originalFontSources = Aspose.Words.Fonts.FontSettings.DefaultInstance.GetFontsSources();
    //int cc1 = originalFontSources.Length;

    // 使用“SetFontsFolder”方法设置一个目录,作为新的字体源。
    Aspose.Words.Fonts.FontSettings.DefaultInstance.SetFontsFolder(FontsDir, true);


    return doc;
}

我指定了SimSun字体,输出word布局正确,当我检测保存的word,发现word没有SimSun字体。
360截图166403268471107.jpg (84.9 KB)

以下是我的检测代码:

        Aspose.Words.Document doc1 = new Aspose.Words.Document(jnMlPath);
        Aspose.Words.Fonts.FontInfoCollection allFonts = doc1.FontInfos;
        string con = "";
        // 打印文档中所有使用和未使用的字体。
        for (int i = 0; i < allFonts.Count; i++)
        {
            //Console.WriteLine($"Font index #{i}");
            //Console.WriteLine($"\tName: {allFonts[i].Name}");
            //Console.WriteLine($"\tIs {(allFonts[i].IsTrueType ? "" : "not ")}a trueType font");
            string ccc1 = $"Font index #{i}";
            string ccc2 = $"\tName: {allFonts[i].Name}";
            string ccc3 = $"\tIs {(allFonts[i].IsTrueType ? "" : "not ")}a trueType font";

            con += ccc1 + "-" + ccc2 + "" + ccc3 + "==";
        }

con变量等于:

Font index #0- Name: Times New Roman Is a trueType font==Font index #1- Name: Symbol Is a trueType font==Font index #2- Name: Arial Is a trueType font==

你好!

1,当我使用内容边距代码,发现LayoutCollector计算任然会出错,任然会多出一页。

        builder.EndTable();

        
        //表格内容边框填充  对于表格中的每个单元格,设置其内容与每个边框之间的距离。 
        //此表将通过环绕文本来保持最小填充距离。
        table.TopPadding = 3;
        table.BottomPadding = 3;
        table.LeftPadding = 3;
        table.RightPadding = 3;
        table.PreferredWidth = Aspose.Words.Tables.PreferredWidth.FromPoints(250);


        //为了检测页面的结束位置,我们将使用LayoutCollector。
        Aspose.Words.Layout.LayoutCollector collector = new Aspose.Words.Layout.LayoutCollector(doc);
        ............................................................

@fhn123456 这是您的代码,其中包含我之前建议的修改:

//Aspose.doc 生成卷内表格
Aspose.Words.Document asposeDoc = new Aspose.Words.Document();
asposeDoc.WarningCallback = new WarningCallback();

//Aspose生成表格方法
AsposeWord(asposeDoc, dhAjH);
private class WarningCallback : IWarningCallback
{
    public void Warning(WarningInfo info)
    {
        if (info.WarningType == WarningType.FontSubstitution)
            Console.WriteLine(info.Description);
    }
}
/// <summary>
/// Aspose.doc生成table
/// </summary>
/// <param name="asposeDoc"></param>
/// <param name="dhAjH"></param>
private static void AsposeWord(Aspose.Words.Document doc, string dhAjH)
{
    Aspose.Words.DocumentBuilder builder = new Aspose.Words.DocumentBuilder(doc);

    //设置字体
    builder.Font.Name = "SimSun";

    builder.PageSetup.TopMargin = 30;
    builder.PageSetup.BottomMargin = 30;
    builder.PageSetup.LeftMargin = 70;
    builder.PageSetup.RightMargin = 30;

    //A4 (595.3x841.9pt)  21cm×29.7cm(210mm×297mm)
    builder.PageSetup.PaperSize = Aspose.Words.PaperSize.A4;

    Aspose.Words.Tables.Table table = builder.StartTable();

    // 第一行  卷内目录
    builder.InsertCell();

    //标题 每页继承
    builder.RowFormat.HeadingFormat = true;
    //文字对齐方式
    builder.ParagraphFormat.Alignment = Aspose.Words.ParagraphAlignment.Center;
    builder.CellFormat.Width = 495.3;
    builder.CellFormat.Borders.LineStyle = Aspose.Words.LineStyle.None;
    builder.Font.Size = 20;
    builder.Font.Bold = true;
    builder.Write("卷 内 文 件 目 录");
    builder.EndRow();

    // 第二行
    builder.InsertCell();
    builder.CellFormat.Width = 495.3;
    builder.CellFormat.Borders.LineStyle = Aspose.Words.LineStyle.None;
    builder.CellFormat.Borders.Bottom.LineStyle = Aspose.Words.LineStyle.Single;
    builder.ParagraphFormat.Alignment = Aspose.Words.ParagraphAlignment.Right;
    builder.Font.Size = 13;
    builder.Font.Bold = true;
    builder.Write(dhAjH);
    builder.RowFormat.HeadingFormat = true;
    builder.EndRow();

    // 第三行
    builder.InsertCell();
    //设置单元格内容对齐方式  垂直对齐
    builder.CellFormat.VerticalAlignment = Aspose.Words.Tables.CellVerticalAlignment.Center;
    builder.ParagraphFormat.Alignment = Aspose.Words.ParagraphAlignment.Center;
    builder.CellFormat.Borders.LineStyle = Aspose.Words.LineStyle.Single;
    builder.CellFormat.Borders.Top.LineStyle = Aspose.Words.LineStyle.Single;
    builder.RowFormat.HeadingFormat = true;

    builder.CellFormat.Width = 20;
    builder.Font.Size = 13;
    builder.Font.Bold = true;
    builder.Write("顺\n序\n号");

    builder.InsertCell();
    builder.CellFormat.Width = 80;
    builder.Write("文号");

    builder.InsertCell();
    builder.CellFormat.Width = 80;
    builder.Write("责任者");

    builder.InsertCell();
    builder.CellFormat.Width = 225.3;
    builder.Write("题   名");

    builder.InsertCell();
    builder.CellFormat.Width = 40;
    builder.Write("日期");

    builder.InsertCell();
    builder.CellFormat.Width = 30;
    builder.Write("页号");

    builder.InsertCell();
    builder.CellFormat.Width = 20;
    builder.Write("备注");
    builder.EndRow();

    //结束标题继承
    builder.RowFormat.HeadingFormat = false;

    //填充数据
    for (int i = 0; i < groupingTable.Rows.Count; i++)
    {

        for (int j = 0; j < 7; j++)
        {
            //添加一个单元格
            builder.InsertCell();
            builder.Font.Bold = false;
            builder.Font.Name = "SimSun";
            builder.Font.Size = 12;
            string clee = "";

            switch (j)
            {

                case 0:
                    builder.CellFormat.Width = 20;
                    clee = serialNo.ToString();
                    break;

                case 1:
                    builder.CellFormat.Width = 80;
                    clee = groupingTable.Rows[i][1].ToString();

                    break;
                case 2:
                    builder.CellFormat.Width = 80;
                    clee = groupingTable.Rows[i][2].ToString();
                    break;

                case 3:
                    builder.CellFormat.Width = 225.3;
                    clee = groupingTable.Rows[i][3].ToString();
                    break;

                case 4:
                    builder.CellFormat.Width = 40;
                    clee = groupingTable.Rows[i][4].ToString();
                    break;

                case 5:
                    builder.CellFormat.Width = 30;
                    clee = groupingTable.Rows[i][5].ToString();
                    break;

                case 6:
                    builder.CellFormat.Width = 20;
                    break;

            }

            builder.Write(clee);

        }
        //序号自增
        serialNo++;

        //结束行
        builder.EndRow();
    }

    builder.EndTable();

    //自动调整
    table.AutoFit(Aspose.Words.Tables.AutoFitBehavior.FixedColumnWidths);
    table.AllowAutoFit = false;

    //用空行填充页面上的剩余空间。
    Aspose.Words.Tables.Row emptyRow = (Aspose.Words.Tables.Row)table.LastRow.Clone(true);
    //获取子节点
    emptyRow.GetChildNodes(Aspose.Words.NodeType.Paragraph, true).Clear();
    emptyRow.RowFormat.Height = 50;

    //为了检测页面的结束位置,我们将使用LayoutCollector。
    Aspose.Words.Layout.LayoutCollector collector = new Aspose.Words.Layout.LayoutCollector(doc);

    //下一个同级 不会多出一页空白页
    int lastRowPageIndex = collector.GetEndPageIndex(table.NextSibling);

    //获取结束页面索引 如果总共3页 
    while (collector.GetEndPageIndex(table.NextSibling) == lastRowPageIndex)//不会出现一页空白页
    {
        //克隆
        table.AppendChild(emptyRow.Clone(true));
        //重置收集器。
        collector = new Aspose.Words.Layout.LayoutCollector(doc);
    }

    //删除最后一个冗余行。
    table.LastRow.Remove();

    string dir = $"{excelFolder}\\卷内目录\\{excelFileName}";

    //如果文件夹不存在就创建
    if (!Directory.Exists(dir))
    {
        Directory.CreateDirectory(dir);
    }

    string jnMlPath = Path.Combine(dir, dhAjH + ".docx");

    //保存文档  
    doc.Save(jnMlPath);
}

Times New Roman 是默认字体,但在您的代码中使用 SimSun:

builder.Font.Name = "SimSun";

非常感谢您的回复和帮助!
1,您给我的代码并没有我需要看到的代码,我想参考您如何指定“字体”路径的代码!

2,当我使用内容边距代码,发现LayoutCollector计算任然会出错,任然会多出一页。

builder.EndTable();

//表格内容边框填充  对于表格中的每个单元格,设置其内容与每个边框之间的距离。 
//此表将通过环绕文本来保持最小填充距离。
table.TopPadding = 3;
table.BottomPadding = 3;
table.LeftPadding = 3;
table.RightPadding = 3;
table.PreferredWidth = Aspose.Words.Tables.PreferredWidth.FromPoints(250);

//为了检测页面的结束位置,我们将使用LayoutCollector。
Aspose.Words.Layout.LayoutCollector collector = new Aspose.Words.Layout.LayoutCollector(doc);
............................................................

@fhn123456

  1. 您可以将所需的字体放入任何可访问的文件夹中,并将其用作附加字体源。 例如看下面的代码:
Document doc = new Document(@"C:\Temp\in.docx");
// Specify where Aspose.Words will look for fonts.
doc.FontSettings = new FontSettings();
doc.FontSettings.SetFontsSources(new FontSourceBase[] { new SystemFontSource(), new FolderFontSource(@"C:\Temp\fonts\", true) });
// now you can list the fonts avaialbe in the specified font sources (for testing purposes)
foreach (FontSourceBase src in doc.FontSettings.GetFontsSources())
{
    foreach (PhysicalFontInfo fontInfo in src.GetAvailableFonts())
        Console.WriteLine(fontInfo.FullFontName);
}
// Now you can process or convert your document 
// ....................

另外,请参阅我们的文档:
https://docs.aspose.com/words/net/specifying-truetype-fonts-location/

  1. 不幸的是,我无法在我这边重现你的问题。 出于测试目的,您可以将文档另存为 PDF。 Aspose.Words 在 LayoutCollector 中使用蹩脚的布局引擎,用于构建文档布局以转换为 PDF。

您好,非常感谢您的帮助!
对于问题2,您无法重现我的问题,我将项目dome通过邮箱发送给您了,请您注意查收!

1,这行代码使用它就会出现LayoutCollector检测页号错误,如果不使用就会正常!

//table.TopPadding = 3;
//table.BottomPadding = 3;
//table.LeftPadding = 3;
//table.RightPadding = 3;

问题2,错误dox截图: