冰蓝科技
|
028-81705109
|
|
微信扫一扫
|

Spire.Cloud 纯前端文档控件

Word模板是企业业务流转的底座,HR 需要标准的劳动合同和录用通知书,销售需要专业的报价单和报告模板,行政需要统一的会议通知和证明文件。Spire.Agent.Office 的 Word AI 能力只需用自然语言描述想要的模板样式和内容结构,比如“包含‘姓名 职位部门 薪资 开始日期 结束日期 合同类型 试用期月份 地点’字段的邮件合并域的合同模板”,AI 即可直接制作交付。

对比传统SDK API处理

传统 Spire.Office for .NET API Spire.Agent.Office
开发方式 调用 API 逐行逐段构建文档结构 使用自然语言描述模板样式和结构,AI 自动编排并生成完整模板文档
代码量 每个模板需编写数百行文档构建代码 仅需 1 条自然语言指令
样式调整 字体、颜色、边框等样式,通过代设置排版非常复杂 直接自然指令描述即可
模板灵活性 模板结构变更需重写底层文档构建逻辑,维护成本高 调整指令描述,AI 即可重新生成,灵活响应需求变化

几类典型业务场景的Word 模板制作:

有关产品安装和 SpireToken 配置,请参考 在 .NET 项目中集成 Spire.Agent.Office。以下示例默认已安装 Spire.Agent.Office 并完成 SpireToken 配置。


Word劳动合同模板

人力资源部门最常用的劳动合同都有相对固定的结构:标题、当事人信息、正文条款、签署栏等。

using Spire.Agent.Office.AI;
using Spire.Agent.Office.Extensions;
using Spire.Doc;

string inputPath = @"";
// 结果文档路径
string savePath = @"合并模板.docx"; ;
// SpireToken Key
string key = "s******************************r";
// 自然语言指令
string instruction =
    "生成一份Word劳动合同模板。" +
    "主标题为'劳动合同',二号字,加粗,居中。" +
    "正文全部使用仿宋字体,小四号(12pt),段落首行缩进2字符。" +
    "整篇文档添加'E-iceblue'淡蓝色水印字样。" +
    "包含以下字段的邮件合并域:姓名、职位部门、薪资、开始日期、结束日期、合同类型、试用期月份、地点。" +
    "整体风格正式专业,符合法律文书场景。";
// AI 生成
AIResult result = ExecuteAIWord(instruction, inputPath, savePath, key);

// Word AI 处理
static AIResult ExecuteAIWord(string instruction, string inputPath, string savePath, string key)
{
    // 创建 AI 处理器选项实例
    AIOptions options = new AIOptions();
    options.SpireToken = key;
    // 创建 Word 文档对象
    using (Document doc = new Document())  
    {
        if (!string.IsNullOrEmpty(inputPath) && File.Exists(inputPath))
        {
            doc.LoadFromFile(inputPath);  
        }
        // 创建 AI 文档处理器实例
         AIDocumentProcessor processor = doc.AI(options);  

        // 根据指令处理文档,并保存结果到指定路径
        return processor.ExecuteInstruction(doc, instruction, savePath);
    }
}

Word劳动合同模板


Word报价单模板

销售与商务部门最常用的报价单都有相对固定的结构:标题、公司信息、客户信息、产品报价表格、金额汇总、报价条款、签署栏等。

using Spire.Agent.Office.AI;
using Spire.Agent.Office.Extensions;
using Spire.Doc;

string inputPath = @"";
// 结果文档路径
string savePath = @"报价单模板.docx"; ;
// SpireToken Key
string key = "s******************************r";
// 自然语言指令
string instruction =
    "生成一份专业的报价单模板,样式要求如下:" +
    "主标题为'报价单',一号字,加粗,居中,使用微软雅黑字体。" +
    "正文使用宋体,小四号(12pt),1.5倍行距。" + "模板结构包含:公司Logo占位区、公司信息(地址、电话、邮箱)、客户信息(客户名称、联系人)、产品报价表格(包含序号、产品名称、规格、数量、单价、小计、备注)、总价(大写+小写)、报价有效期、公司签章区。\n" +
    "在模板中使用{{}}作为占位符标记,例如:{{公司名称}}、{{客户名称}}、{{产品名称}}、{{单价}}、{{数量}}、{{小计}}、{{总价大写}}、{{总价小写}}。";

// AI 生成
AIResult result = ExecuteAIWord(instruction, inputPath, savePath, key);

// Word AI 处理
static AIResult ExecuteAIWord(string instruction, string inputPath, string savePath, string key)
{
    // 创建 AI 处理器选项实例
    AIOptions options = new AIOptions();
    options.SpireToken = key;
    // 创建 Word 文档对象
    using (Document doc = new Document())  
    {
        if (!string.IsNullOrEmpty(inputPath) && File.Exists(inputPath))
        {
            doc.LoadFromFile(inputPath);  
        }
        // 创建 AI 文档处理器实例
         AIDocumentProcessor processor = doc.AI(options);  

        // 根据指令处理文档,并保存结果到指定路径
        return processor.ExecuteInstruction(doc, instruction, savePath);
    }
}

Word报价单模板


Word证书模板

证书模板在培训认证、表彰奖励、活动参与等场景中被广泛使用,其核心结构通常包括:证书标题(如“荣誉证书”“结业证书”等)、证书编号等。

using Spire.Agent.Office.AI;
using Spire.Agent.Office.Extensions;
using Spire.Doc;

string inputPath = @"";
// 结果文档路径
string savePath = @"Word证书模板.docx"; ;
// SpireToken Key
string key = "s******************************r";
// 自然语言指令
string instruction =
"生成一页的荣誉证书模板,样式要求如下:" +
"整体采用古典庄重风格,添加金色双线边框,使用华文中宋字体" +
"顶部居中放置证书标题:'荣誉证书'——初号字,加粗,金色" +
"正文区域居中布局,内容结构为:" +
"  第一行:'兹证明';" +
"  第二行:'{{姓名}}'字体加粗,红色;" +
"  第三行:'在{{年份}}年度工作中表现优异,被评为:'" +
"  第四行:'{{荣誉称号}}'字体加粗,金色" +
"  第五行:'特发此证,以资鼓励。'。" +
"落款区域:右下角分两行显示'{{颁发单位}}'和'{{日期}}',右对齐。" +
"左下角添加证书编号:'编号:{{证书编号}}'。" +
"整体风格正式、庄重、大气,适合政府或企业颁发的荣誉证书场景。";

// AI 生成
AIResult result = ExecuteAIWord(instruction, inputPath, savePath, key);

// Word AI 处理
static AIResult ExecuteAIWord(string instruction, string inputPath, string savePath, string key)
{
    // 创建 AI 处理器选项实例
    AIOptions options = new AIOptions();
    options.SpireToken = key;
    // 创建 Word 文档对象
    using (Document doc = new Document())  
    {
        if (!string.IsNullOrEmpty(inputPath) && File.Exists(inputPath))
        {
            doc.LoadFromFile(inputPath);  
        }
        // 创建 AI 文档处理器实例
         AIDocumentProcessor processor = doc.AI(options);  

        // 根据指令处理文档,并保存结果到指定路径
        return processor.ExecuteInstruction(doc, instruction, savePath);
    }
}

Word证书模板


预算报告模板

预算报告模板是企业或组织在进行财务规划、项目申报、年度计划时常用的文档工具,其核心结构通常包括:报告标题(如“××年度预算报告”“××项目预算方案”)、编制单位与日期、预算编制说明等。

using Spire.Agent.Office.AI;
using Spire.Agent.Office.Extensions;
using Spire.Doc;

string inputPath = @"";
// 结果文档路径
string savePath = @"预算报告模板.docx"; ;
// SpireToken Key
string key = "s******************************r";
// 自然语言指令
string instruction =
"生成一份专业的预算报告模板,样式要求如下:" +
"主标题'{{年度}}年度预算报告'——一号字,加粗,居中,使用微软雅黑。" +
"标题下方添加副标题:'编制单位:{{部门名称}} | 编制日期:{{编制日期}}',小四号,居中。" +
"正文部分分为四个区域:\n" +
"  区域一(预算总览):顶部用卡片式布局展示四项关键指标——'年度预算总额:{{预算总额}}万元'、'已执行金额:{{已执行}}万元'、'执行率:{{执行率}}%'、'剩余预算:{{剩余预算}}万元',四个数据用浅色底纹框并列显示,数字加粗放大。\n" +
"  区域二(预算明细表):详细预算表,包含列——科目编码、科目名称、年度预算(万元)、Q1执行、Q2执行、Q3执行、Q4执行、已执行合计、执行率(%)、剩余预算(万元)。表头背景深绿色(#1E5631),白色加粗字体;数字列保留两位小数;数据行交替颜色。\n" +
"  区域四(预算说明):页面底部添加'预算说明'区域——'{{预算编制说明}}'。\n" +
"整体风格规范大气,适合向管理层汇报的正式预算报告场景。";

// AI 生成
AIResult result = ExecuteAIWord(instruction, inputPath, savePath, key);

// Word AI 处理
static AIResult ExecuteAIWord(string instruction, string inputPath, string savePath, string key)
{
    // 创建 AI 处理器选项实例
    AIOptions options = new AIOptions();
    options.SpireToken = key;
    // 创建 Word 文档对象
    using (Document doc = new Document())  
    {
        if (!string.IsNullOrEmpty(inputPath) && File.Exists(inputPath))
        {
            doc.LoadFromFile(inputPath);  
        }
        // 创建 AI 文档处理器实例
         AIDocumentProcessor processor = doc.AI(options);  

        // 根据指令处理文档,并保存结果到指定路径
        return processor.ExecuteInstruction(doc, instruction, savePath);
    }
}

预算报告模板


常见问题

生成的模板样式与预期不完全一致

原因:指令中的样式描述不够具体。

解决:在指令中明确指定字体名称等细节。

已经生成的模板需要修改

原因:业务需求变化导致模板需要调整。

解决:直接在指令中描述修改内容重新生成,或者将当前文档作为输入文件,使用AI二次操作。

生成的模板中文乱码或字体不正确

原因:系统中缺少指令中指定的字体。

解决:确保系统安装了指令中提到的字体。或在指令中使用常见系统字体。


获取SpireToken Key

  • 联系 该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。 或访问 https://www.e-iceblue.com/TemLicense.html 获得试用/商业 API 密钥

在代码中配置:

AIOptions options = new AIOptions();
options.SpireToken = key;

数据透视图是以图形方式直观展示数据透视表汇总结果的图表,它让数据比较与趋势一目了然,是进行数据分析与报表展示的重要工具。Spire.XLS for JavaScript 基于 WebAssembly 在浏览器端直接完成对 Excel 数据透视图的创建、字段按钮控制与系列格式设置,通过虚拟文件系统(VFS)管理输入输出文件,无需后端服务支持。它提供了完整的 API 用于创建基于数据透视表的数据透视图、控制数据透视图字段按钮的显示与隐藏,以及自定义数据透视图系列的外观格式。

本文介绍三个核心功能点:

有关安装和项目配置,请参考 React 项目中集成 Spire.XLS for JavaScript。以下示例默认已安装 Spire.XLS 并完成 WebAssembly 模块初始化。


在 Excel 中创建数据透视图

数据透视图必须基于数据透视表来创建。Spire.XLS for JavaScript 支持在工作表中先创建数据透视表,再通过 Charts.Add() 方法指定 pivotChartType 和 pivotTable 参数,基于该数据透视表直接生成对应的数据透视图。具体操作步骤如下:

  1. 创建 Workbook 对象并获取默认工作表。
  2. 在工作表中填入数据透视表所需的源数据。
  3. 使用 PivotCaches.Add() 创建数据透视表缓存。
  4. 使用 PivotTables.Add() 添加数据透视表,并将字段拖至行区域和数据区域。
  5. 使用 sheet.Charts.Add() 添加图表,并通过 pivotChartType 和 pivotTable 参数基于数据透视表创建数据透视图。
  6. 设置数据透视图的位置和标题。
  7. 使用 SaveToFile() 保存工作簿为 Excel 文件。

下面是一个完整的代码示例,展示了在 React 中基于数据透视表创建数据透视图:

function App() {
  const createPivotChart = async () => {
    // 获取 Spire.XLS WASM 模块
    const xlsModule = window.wasmModule?.spirexls;

    // 检查模块是否就绪
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // 将中文字体加载到虚拟文件系统(VFS)
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);

    // 创建新工作簿并获取默认工作表
    const workbook = new xlsModule.Workbook();
    let sheet = workbook.Worksheets.get(0);

    // 填入数据透视表的源数据
    sheet.Range.get('A1').Value = '产品';
    sheet.Range.get('B1').Value = '月份';
    sheet.Range.get('C1').Value = '销量';

    sheet.Range.get('A2').Value = '苹果';
    sheet.Range.get('A3').Value = '苹果';
    sheet.Range.get('A4').Value = '香蕉';
    sheet.Range.get('A5').Value = '苹果';
    sheet.Range.get('A6').Value = '香蕉';
    sheet.Range.get('A7').Value = '香蕉';

    sheet.Range.get('B2').Value = '一月';
    sheet.Range.get('B3').Value = '二月';
    sheet.Range.get('B4').Value = '一月';
    sheet.Range.get('B5').Value = '一月';
    sheet.Range.get('B6').Value = '二月';
    sheet.Range.get('B7').Value = '二月';

    sheet.Range.get('C2').Value = '10';
    sheet.Range.get('C3').Value = '15';
    sheet.Range.get('C4').Value = '9';
    sheet.Range.get('C5').Value = '7';
    sheet.Range.get('C6').Value = '8';
    sheet.Range.get('C7').Value = '10';

    // 创建数据透视表
    let dataRange = sheet.Range.get('A1:C7');
    let cache = workbook.PivotCaches.Add({ range: dataRange });
    let pivotTable = sheet.PivotTables.Add('数据透视表', sheet.Range.get({ row: 1, column: 5 }), cache);

    // 将字段拖到行区域
    let pf = pivotTable.PivotFields.get_Item('产品');
    pf.Axis = xlsModule.AxisTypes.Row;
    let pf2 = pivotTable.PivotFields.get_Item('月份');
    pf2.Axis = xlsModule.AxisTypes.Row;

    // 将字段拖到数据区域
    pivotTable.DataFields.Add(pivotTable.PivotFields.get_Item('销量'), '求和项:销量', xlsModule.SubtotalTypes.Sum);

    // 设置数据透视表样式并计算结果
    pivotTable.BuiltInStyle = xlsModule.PivotBuiltInStyles.PivotStyleMedium12;
    pivotTable.CalculateData();

    // 基于数据透视表创建簇状柱形图
    let chart = sheet.Charts.Add({ pivotChartType: xlsModule.ExcelChartType.ColumnClustered, pivotTable: pivotTable });
    // 设置数据透视图位置
    chart.TopRow = 9;
    chart.LeftColumn = 1;
    chart.RightColumn = 9;
    chart.BottomRow = 25;
    // 设置数据透视图标题
    chart.ChartTitle = "数据透视图";

    // 保存工作簿
    const outputFileName = 'PivotChart.xlsx';
    workbook.SaveToFile(outputFileName);
    workbook.Dispose();

    // 从 VFS 读取文件,触发下载
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Create Pivot Chart</h1>
      <button onClick={createPivotChart}>
        Generate
      </button>
    </div>
  );
}

export default App;

使用 Spire.XLS for JavaScript 在 Excel 中创建数据透视图后的效果

使用 Spire.XLS for JavaScript 在 Excel 中创建数据透视图


显示或隐藏 Excel 数据透视图的字段按钮

默认情况下,数据透视图会显示字段按钮,方便用户交互式地筛选和切换字段数据。在生成报表时,您可能希望隐藏部分或全部字段按钮,使图表更加简洁。Spire.XLS for JavaScript 提供了 DisplayEntireFieldButtons、DisplayValueFieldButtons、DisplayAxisFieldButtons、DisplayLegendFieldButtons 和 ShowReportFilterFieldButtons 等属性,用于灵活控制各类型字段按钮的显示与隐藏。具体操作步骤如下:

  1. 创建 Workbook 对象并加载包含数据透视图的已有 Excel 文件。
  2. 通过 workbook.Worksheets.get() 获取工作表。
  3. 使用 sheet.Charts.get() 获取数据透视图对象。
  4. 通过 DisplayEntireFieldButtons 控制是否显示全部字段按钮。
  5. 通过 DisplayValueFieldButtons、DisplayAxisFieldButtons、DisplayLegendFieldButtons 和 ShowReportFilterFieldButtons 分别控制各类型字段按钮的显示与隐藏。
  6. 使用 SaveToFile() 保存工作簿为 Excel 文件。

下面是一个完整的代码示例,展示了在 React 中显示或隐藏数据透视图的字段按钮(示例加载上一节生成的数据透视图文件 PivotChart.xlsx):

function App() {
  const showHideFieldButtons = async () => {
    // 获取 Spire.XLS WASM 模块
    const xlsModule = window.wasmModule?.spirexls;

    // 检查模块是否就绪
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // 将包含数据透视图的示例文件加载到虚拟文件系统(VFS)
    let excelFileName = 'PivotChart.xlsx';
    await window.spire.FetchFileToVFS(excelFileName, '', `${process.env.PUBLIC_URL}data/`);

    // 创建新工作簿并加载已有文件
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: excelFileName });

    // 获取第一个工作表
    let sheet = workbook.Worksheets.get(0);

    // 获取数据透视图
    let chart = sheet.Charts.get(0);

    // 控制全部字段按钮的显示
    chart.DisplayEntireFieldButtons = true;

    // 隐藏数值字段按钮
    chart.DisplayValueFieldButtons = false;
    // 隐藏坐标轴字段按钮
    chart.DisplayAxisFieldButtons = false;
    // 隐藏图例字段按钮
    //chart.DisplayLegendFieldButtons = false;
    // 显示报表筛选字段按钮
    //chart.ShowReportFilterFieldButtons = true;

    // 保存工作簿
    const outputFileName = 'PivotChartFieldButtons.xlsx';
    workbook.SaveToFile(outputFileName);
    workbook.Dispose();

    // 从 VFS 读取文件,触发下载
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Show/Hide PivotChart Field Buttons</h1>
      <button onClick={showHideFieldButtons}>
        Generate
      </button>
    </div>
  );
}

export default App;

使用 Spire.XLS for JavaScript 显示或隐藏数据透视图字段按钮后的效果

使用 Spire.XLS for JavaScript 显示或隐藏数据透视图字段按钮


给 Excel 数据透视图系列设置格式

对数据透视图的系列进行格式化,可以让图表更加美观、层次分明,从而更清晰地传达数据信息。Spire.XLS for JavaScript 支持加载包含数据透视图的 Excel 文件,通过 Charts.get() 方法获取数据透视图,再通过系列的 DataFormat 属性设置填充类型、颜色与边框样式,并通过 GetCommonSerieFormat() 方法返回的格式对象设置数据条宽度等格式。具体操作步骤如下:

  1. 创建 Workbook 对象。
  2. 使用 LoadFromFile() 方法加载包含数据透视图的 Excel 文件。
  3. 使用 Worksheets.get() 方法获取 Excel 文件中的特定工作表。
  4. 使用 Charts.get() 方法获取工作表中的数据透视图。
  5. 设置数据透视图的位置和标题。
  6. 使用 Series.get() 方法获取数据透视图的数据系列。
  7. 通过 DataFormat 属性设置系列的填充类型、颜色与边框样式,并通过 GetCommonSerieFormat() 方法设置数据条宽度等格式。
  8. 使用 SaveToFile() 方法保存生成的文件。

下面是一个完整的代码示例,展示了在 React 中给数据透视图的系列设置格式(示例加载上一节生成的数据透视图文件 PivotChart.xlsx):

function App() {
  const formatPivotChartSeries = async () => {
    // 获取 Spire.XLS WASM 模块
    const xlsModule = window.wasmModule?.spirexls;

    // 检查模块是否就绪
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // 将包含数据透视表的示例文件加载到虚拟文件系统(VFS)
    let excelFileName = 'PivotChart.xlsx';
    await window.spire.FetchFileToVFS(excelFileName, '', `${process.env.PUBLIC_URL}data/`);

    // 创建 Workbook 对象
    const workbook = new xlsModule.Workbook();
    // 加载 Excel 文件
    workbook.LoadFromFile({ fileName: excelFileName });

    // 获取第一个工作表
    let sheet = workbook.Worksheets.get(0);

    //获取数据透视图
    let chart = sheet.Charts.get(0);

    // 设置数据透视图位置
    chart.TopRow = 1;
    chart.LeftColumn = 8;
    chart.RightColumn = 18;
    chart.BottomRow = 15;

    // 设置图表标题
    chart.ChartTitle = "";

    // 向数据透视图添加系列
    let series = chart.Series.get(0);

    // 设置数据条的宽度
    series.GetCommonSerieFormat().GapWidth = 10;
    // series.GetCommonSerieFormat().Overlap = 100;

    // 设置系列的填充类型与前景色、背景色
    series.DataFormat.Fill.FillType = xlsModule.ShapeFillType.SolidColor;
    series.DataFormat.ForeGroundColor = xlsModule.Color.get_Red();
    series.DataFormat.BackGroundColor = xlsModule.Color.get_White();

    // 设置系列边框的颜色、线型与线宽
    series.DataFormat.LineProperties.Pattern = xlsModule.ChartLinePatternType.Solid;
    series.DataFormat.LineProperties.Color = xlsModule.Color.get_Blue();
    series.DataFormat.LineProperties.CustomLineWeight = 2.5;

    // 为系列添加阴影效果
    series.DataFormat.IsShadow = true;

    // 保存工作簿
    const outputFileName = 'PivotChartSeriesFormat.xlsx';
    workbook.SaveToFile(outputFileName);
    workbook.Dispose();

    // 从 VFS 读取文件,触发下载
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Format PivotChart Series</h1>
      <button onClick={formatPivotChartSeries}>
        Generate
      </button>
    </div>
  );
}

export default App;

使用 Spire.XLS for JavaScript 设置数据透视图系列格式后的效果

使用 Spire.XLS for JavaScript 设置数据透视图系列格式


常见问题

如何刷新数据透视图以显示最新数据?

原因:数据透视图基于数据透视表创建,修改数据透视表的数据源后,图表不会自动同步更新。

解决:在修改数据源后,通过 Cache.IsRefreshOnLoad 属性让数据透视表在文件打开时自动刷新,从而同步更新数据透视图:

// 获取数据透视表
let pivotTable = sheet.PivotTables.get(0);
// 设置在文件打开时自动刷新数据透视表
pivotTable.Cache.IsRefreshOnLoad = true;

为什么数据透视图没有显示任何数据?

原因:数据透视图的系列来源于数据透视表的汇总结果,如果数据透视表未执行计算,或创建数据透视图时未正确关联数据透视表,图表可能会显示为空白。

解决:创建数据透视表后调用 CalculateData() 方法计算结果,并在创建数据透视图时通过 pivotTable 参数正确关联数据透视表:

// 计算数据透视表的结果
pivotTable.CalculateData();

// 基于数据透视表创建数据透视图
let chart = sheet.Charts.Add({ pivotChartType: xlsModule.ExcelChartType.ColumnClustered, pivotTable: pivotTable });

获取免费许可证

如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。

在传统的 Spire.Office for .NET 组件文档处理场景中,开发者需要熟悉产品 API 接口编写大量代码来实现格式设置、数据提取、文档转换等操作。Spire.Agent.Office 通过引入 AI 层使用 自然语言指令 来完成这些任务,告别繁琐的代码编写。

本教程将介绍如何在 .NET 10 项目中集成使用 Spire.Agent.Office 实现文档处理的 AI 化(本产品基于 .NET Standard 2.1 开发,兼容 .NET 5/6/7/8等多个平台,不限于.NET 10)。


为什么选择 Spire.Agent.Office

Spire.Agent.Office 是基于 Spire.Office for .NET 传统 API 文档引擎之上构建的 AI 智能体,与传统的 Spire.Office for .NET 组件的核心区别在于:

传统 Spire.Office for .NET Spire.Agent.Office
操作方式 手写代码(调用 API 接口、遍历文档数据、操作处理、保存结果) 自然语言指令(如 "合同审查")
使用门槛 需要了解详细的 API 和对象结构 只需描述需求,AI 自动执行
灵活性 API 代码处理可能不适合所有文档 通用 AI 指令可以处理所有文档

工作原理

自然语言指令 → Spire.Agent.Office AI 层 → Spire.Office 文档引擎 → 输出文件

Spire.Agent.Office 解析您的自然语言指令,将其转换为 Spire.Office 文档引擎的内部调用处理文档,最终生成预期文档,支持 Word、Excel、PowerPoint、PDF 等多种文档格式处理和转换。

核心优势

优势 说明
AI 原生体验 告别繁琐的 API 调用链,用自然语言直接实现文档处理
稳定可靠性 基于成熟的 Spire.Office 文档引擎构建,保证文档处理的效果
无缝集成 支持跨平台使用,轻松集成,可灵活对接业务逻辑,实现功能拓展需求
灵活 AI 模型支持 兼容主流 AI 基础设施,保证 AI 代码生成准确率
加速开发交付 缩短文档处理任务开发时间

项目搭建与库引用

创建 .NET 10 平台的项目

创建 .NET 10 项目

通过 NuGet 安装 Spire.Agent.Office 产品

NuGet 安装 Spire.Agent.Office后相应依赖会自动安装

NuGet 安装 Spire.Agent.Office

通过本地导入 Spire.Agent.Office 程序集

从网站下载 Spire.Agent.Office解压至本地目录后导入项目 本地导入程序集

通过本地 Dll 添加,需要同时添加以下依赖,以保证更好的运行效果:

依赖包 最低版本
coverlet.collector >= 6.0.4
Microsoft.CodeAnalysis >= 4.5.0
Microsoft.Data.Sqlite >= 8.0.0
Microsoft.Extensions.Caching.Memory >= 8.0.0
Microsoft.Extensions.Configuration >= 8.0.0
Microsoft.Extensions.Configuration.Abstractions >= 8.0.0
Microsoft.Extensions.Configuration.EnvironmentVariables >= 8.0.0
Microsoft.Extensions.Configuration.Json >= 8.0.0
Microsoft.Extensions.DependencyInjection >= 8.0.0
Microsoft.Extensions.Hosting.Abstractions >= 8.0.0
Microsoft.Extensions.Http >= 8.0.0
Microsoft.Extensions.Http.Polly >= 8.0.0
Microsoft.Extensions.Logging >= 8.0.0
Microsoft.Extensions.Logging.Abstractions >= 8.0.0
Microsoft.Extensions.Logging.Console >= 8.0.0
Microsoft.Extensions.Options >= 8.0.0
Microsoft.ML.OnnxRuntime >= 1.16.1
Microsoft.NET.Test.Sdk >= 17.12.0
Polly >= 8.0.0
Polly.Extensions.Http >= 3.0.0
PolySharp >= 1.4.0
Serilog >= 4.3.0
Serilog.Extensions.Logging >= 7.0.0
Serilog.Sinks.File >= 6.0.0
SkiaSharp >= 3.116.1
Spire.Docfor.NETStandard >= 14.8.0
Spire.PDFfor.NETStandard >= 12.8.3
Spire.Presentationfor.NETStandard >= 11.8.2
Spire.XLSfor.NETStandard >= 16.8.2
System.Text.Json >= 10.0.10
xunit >= 2.9.2
xunit.runner.visualstudio >= 2.8.2

文档处理 AI 化的实现

核心流程

文档 AI 处理主要遵循以下模式:

  1. 创建文档对象(Workbook / Document / PdfDocument / Presentation)
  2. 加载预设文档(可选,也可以为空新创建文档)
  3. AIOptions 配置(设置 SpireToken)
  4. 调用 .AI(options) 获取 AIDocumentProcessor
  5. 执行 AI 指令,并根据返回监测执行状态:
    • 处理现有文档:调用 AIDocumentProcessor.ExecuteInstruction(),返回 AIResult
    • 生成 PPT 文档:调用 AIDocumentProcessor.GeneratePresentation(),返回 GenerationResult

核心代码

using Spire.Agent.Office.AI;
using Spire.Agent.Office.Extensions;
using Spire.Pdf;
using Spire.Doc;
using Spire.Presentation;
using Spire.Xls;

// Excel 处理
static AIResult ExecuteDemoXls(string instruction, string inputPath, string savePath, string key, string[] attachmentPaths)
{
    AIOptions options = new AIOptions();
    options.SpireToken = key;

    using (Workbook workbook = new Workbook())
    {
        // 如果输入路径存在且文件可访问,则加载文档
        if (!string.IsNullOrEmpty(inputPath) && File.Exists(inputPath))
        {
            workbook.LoadFromFile(inputPath);
        }
        // 否则使用空 Workbook
        AIDocumentProcessor processor = workbook.AI(options);
        return processor.ExecuteInstruction(workbook, instruction, savePath, attachmentPaths);
    }
}

// Word 处理
static AIResult ExecuteDemoWord(string instruction, string inputPath, string savePath, string key, string[] attachmentPaths)
{
    AIOptions options = new AIOptions();
    options.SpireToken = key;

    using (Document doc = new Document())
    {
        // 如果输入路径存在且文件可访问,则加载文档
        if (!string.IsNullOrEmpty(inputPath) && File.Exists(inputPath))
        {
            doc.LoadFromFile(inputPath);
        }
        // 否则使用空 Document
        AIDocumentProcessor processor = doc.AI(options);
        return processor.ExecuteInstruction(doc, instruction, savePath, attachmentPaths);
    }
}

// PDF 处理
static AIResult ExecuteDemoPDF(string instruction, string inputPath, string savePath, string key, string[] attachmentPaths)
{
    AIOptions options = new AIOptions();
    options.SpireToken = key;

    using (PdfDocument pdf = new PdfDocument())
    {
        // 如果输入路径存在且文件可访问,则加载文档
        if (!string.IsNullOrEmpty(inputPath) && File.Exists(inputPath))
        {
            pdf.LoadFromFile(inputPath);
        }
        // 否则使用空 PdfDocument
        AIDocumentProcessor processor = pdf.AI(options);
        return processor.ExecuteInstruction(pdf, instruction, savePath, attachmentPaths);
    }
}

// PPT 生成
static PPTGenerationResult GeneratPPT(string input, string instruction, string savePath, string key)
{
    AIOptions options = new AIOptions();
    options.SpireToken = key;

    using (Presentation ppt = new Presentation())
    {
        AIDocumentProcessor processor = ppt.AI(options);
        return processor.GeneratePresentation(input, instruction, savePath);
    }
}

// 基于现有 PPT 的处理
static AIResult ExecuteDemoPPT(string inputPath, string instruction, string savePath, string key, string[] attachmentPaths)
{
    AIOptions options = new AIOptions();
    options.SpireToken = key;

    using (Presentation ppt = new Presentation())
    {
        // 如果输入路径存在且文件可访问,则加载文档
        if (!string.IsNullOrEmpty(inputPath) && File.Exists(inputPath))
        {
            ppt.LoadFromFile(inputPath);
        }
        // 否则使用空 Presentation
        AIDocumentProcessor processor = ppt.AI(options);
        return processor.ExecuteInstruction(ppt, instruction, savePath, attachmentPaths);
    }
}

// 写入日志
static void WriteLog(dynamic? aiResult, string taskName, string basePath)
{
    string logFilePath = Path.Combine(basePath, $"{taskName}.txt");
    string? logDir = Path.GetDirectoryName(logFilePath);
    if (!string.IsNullOrEmpty(logDir) && !Directory.Exists(logDir))
        Directory.CreateDirectory(logDir);

    var logBuilder = new System.Text.StringBuilder();

    // 判断执行状态:成功/失败/跳过
    string status = aiResult == null ? "SKIPPED" :
        aiResult.Success ? "SUCCESS" : $"FAILED: {aiResult.ErrorMessage}";

    logBuilder.AppendLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [{taskName}] {status}");

    if (aiResult != null)
    {
        // 记录执行耗时
        logBuilder.AppendLine($" | Duration: {aiResult.Duration.TotalSeconds:F2}s");

        // 记录 Token 使用统计
        var tu = aiResult.TokenUsage;
        if (tu != null)
        {
            logBuilder.Append($" | In: {tu.InputTokens:N0}");           // 输入 Token 数
            logBuilder.Append($" | Out: {tu.OutputTokens:N0}");         // 输出 Token 数
            logBuilder.Append($" | CacheR: {tu.CacheReadTokens:N0}");   // 缓存读取 Token 数
            logBuilder.Append($" | CacheW: {tu.CacheWriteTokens:N0}");  // 缓存写入 Token 数
            logBuilder.Append($" | CacheT: {tu.TotalCacheTokens:N0}");  // 缓存总 Token 数
            logBuilder.Append($" | Total: {tu.TotalTokens:N0}");        // 总 Token 数
        }
    }

    logBuilder.AppendLine();
    File.AppendAllText(logFilePath, logBuilder.ToString());
}

调用进行 AI 处理

如下面示例,以自然语言为交互方式,调用系统强大的文档处理能力,完成各类复杂的文档任务。

// 多个文档路径添加
string[] attachmentPaths = new string[] { };

// 针对 Word 处理
string inputPath = @"in.docx";
string savePath = @"out.pdf";
string key = "SpireToken key";
string instruction = "查找 '****' 进行高亮,结果保存到 PDF";
AIResult result = ExecuteDemoWord(instruction, inputPath, savePath, key, attachmentPaths);
WriteLog(result, "word", @"log\");

// 针对 PPT 处理
string inputPath = @"in.pptx";
string savePath = @"out.pptx";
string key = "SpireToken key";
string instruction = "将 PPT 每页添加 notes 描述";
AIResult result = ExecuteDemoPPT(instruction, inputPath, savePath, key, attachmentPaths);
WriteLog(result, "ppt", @"log\");

// PPT 生成
string inputPath = @"AI.md";
string savePath = @"out.pptx";
string key = "SpireToken key";
string instruction = "根据 AI.md 生成 PPT 文档";
PPTGenerationResult result = GeneratPPT(inputPath, instruction, savePath, key);
WriteLog(result, "ppt", @"log\");

// 针对 PDF 处理
string inputPath = @"in.pdf";
string savePath = @"out.md";
string key = "SpireToken key";
string instruction = "提取表格数据保存为标准的 markdown 格式";
AIResult result = ExecuteDemoPDF(instruction, inputPath, savePath, key, attachmentPaths);
WriteLog(result, "pdf", @"log\");

// Excel 处理
string inputPath = @"in.xlsx";
string savePath = @"out.pdf";
string key = "SpireToken key";
string instruction = "将文档中空行删除";
AIResult result = ExecuteDemoXls(instruction, inputPath, savePath, key, attachmentPaths);
WriteLog(result, "xls", @"log\");

常见错误处理

SpireToken Key 未正确配置

如果未配置 SpireToken Key,配置的 Key 不正确或者 Key 已失效,Spire.Agent.Office 会抛出异常,程序将中止执行。请先确保 SpireToken Key 的正确有效性。

AI 指令执行失败

ExecuteInstruction 返回的 AIResult 可能包含失败信息,需要检查 Success 属性。

AIResult result = processor.ExecuteInstruction(doc, instruction, outputPath);

if (result == null || !result.Success)
{
    throw new InvalidOperationException(
        $"AI instruction failed: {result?.ErrorMessage ?? "Unknown error"}");
}

加载文档路径不正确

如果针对已有文档处理,文件路径不正确会导致加载文档失败:

  • 保证正确的文档路径
  • 如果需要针对多文档操作(例如文档合并),其它文档可定义在 attachmentPaths 中

申请 SpireToken Key

Spire.Agent.Office 需要配置有效的 SpireToken Key 才能体验完整的功能:

  • 联系 该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。 或访问 https://www.e-iceblue.com/TemLicense.html 获得试用/商业 API 密钥

在代码中配置:

AIOptions options = new AIOptions();
options.SpireToken = key;

在日常办公自动化场景中,经常需要从 Excel 报表中批量提取产品图片、替换过期 Logo,或对指定图片进行单独导出。Spire.XLS for JavaScript 基于 WebAssembly 在浏览器端直接完成这些图片操作,通过虚拟文件系统(VFS)管理输入输出文件,无需后端服务支持。

本文介绍三个核心功能点:

有关安装和项目配置,请参考 React 项目中集成 Spire.XLS for JavaScript。以下示例默认已安装 Spire.XLS 并完成 WebAssembly 模块初始化。


提取工作表中的所有图片

批量提取工作表中的所有图片,适用于备份报表中的嵌入图像、迁移产品资料等场景。实现流程分为三个步骤:遍历 Worksheet.Pictures 集合,对每张图片调用 Picture.Save 方法将其保存到 VFS,然后逐一读取并触发浏览器下载。

function App() {
  const extractAllImages = async () => {
    // 获取 Spire.XLS WASM 模块
    const xlsModule = window.wasmModule?.spirexls;

    // 检查模块是否就绪
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // 将 Excel 文件载入 VFS
    const inputFileName = 'ReadImages.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // 加载工作簿,获取第一个工作表
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });
    const sheet = workbook.Worksheets.get(0);

    // 遍历工作表中的所有图片并逐个导出
    for (let i = 0; i < sheet.Pictures.Count; i++) {
      const pic = sheet.Pictures.get(i);
      const outputFileName = `Image-${i + 1}.png`;
      pic.Picture.Save(outputFileName);

      // 从 VFS 读取导出的图片文件,触发下载
      const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
      const blob = new Blob([fileArray], { type: "image/png" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = outputFileName;
      a.click();
      URL.revokeObjectURL(url);
    }

    // 释放资源
    workbook.Dispose();
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>提取工作表中的所有图片</h1>
      <button onClick={extractAllImages}>
        提取全部图片
      </button>
    </div>
  );
}

export default App;

从工作表中批量提取并下载的图片文件

从工作表中批量提取并下载的图片文件


提取指定图片

提取工作表中的指定图片有两种常用方式:按索引直接获取,或按图片名称遍历匹配。索引方式适合已知图片位置(如第一张图片)的场景,名称方式则适合预先知道图片标识名的情况。实现流程分为两步:先通过索引或名称定位目标图片,再将其导出为本地文件。

function App() {
  const extractImage = async () => {
    // 获取 Spire.XLS WASM 模块
    const xlsModule = window.wasmModule?.spirexls;

    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // 将 Excel 文件载入 VFS
    const inputFileName = 'ReadImages.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // 加载工作簿,获取第一个工作表
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });
    const sheet = workbook.Worksheets.get(0);

    // 方法一:按索引提取(例如提取第二张图片)
    const pic = sheet.Pictures.get(1);
    const outputFileName = 'ExtractByIndex.png';

    // // 方法二:按图片名称遍历匹配
    // let pic = null;
    // const targetName = 'SpireXLS';
    // for (let i = 0; i < sheet.Pictures.Count; i++) {
    //   if (sheet.Pictures.get(i).Name === targetName) {
    //     pic = sheet.Pictures.get(i);
    //     break;
    //   }
    // }
    // const outputFileName = 'ExtractByName.png';

    // 将图片保存到 VFS 并触发下载
    pic.Picture.Save(outputFileName);
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: "image/png" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);

    workbook.Dispose();
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>提取指定图片</h1>
      <button onClick={extractImage}>
        提取图片
      </button>
    </div>
  );
}

export default App;

通过索引或图片名称提取并下载的指定图片

通过索引或图片名称提取并下载的指定图片


替换工作表中的已有图片

替换工作表中的现有图片是更新报表 Logo、更换产品展示图等场景中的常见需求。实现思路是:先获取目标图片的位置与大小信息,然后通过 XlsShape.Convert 将此图片删除,最后在相同位置插入新图片,并将新图片的大小与偏移设置为与原图片一致。

function App() {
  const replaceImage = async () => {
    // 获取 Spire.XLS WASM 模块
    const xlsModule = window.wasmModule?.spirexls;

    // 检查模块是否就绪
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // 将 Excel 文件和新图片载入 VFS
    const inputFileName = 'ReadImages.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
    const newImageFile = 'Logo.png';
    await window.spire.FetchFileToVFS(newImageFile, '', `${process.env.PUBLIC_URL}data/`);

    // 加载工作簿,获取第一个工作表
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });
    const sheet = workbook.Worksheets.get(0);

    // 获取第一张图片及其位置、大小信息
    const oldPic = sheet.Pictures.get(0);
    const topRow = oldPic.TopRow;
    const leftColumn = oldPic.LeftColumn;
    const leftColumnOffset = oldPic.LeftColumnOffset;
    const topRowOffset = oldPic.TopRowOffset;
    const width = oldPic.Width;
    const height = oldPic.Height;

    // 删除原有图片
    xlsModule.XlsShape.Convert(oldPic).Remove();

    // 在同一位置插入新图片
    let picture = sheet.Pictures.Add({ topRow: topRow, leftColumn: leftColumn, fileName: newImageFile });

    // 设置新图片大小与偏移,与原图片保持一致
    picture.Width = width;
    picture.Height = height;
    picture.LeftColumnOffset = leftColumnOffset;
    picture.TopRowOffset = topRowOffset;

    const outputFileName = 'ReplaceImage-out.xlsx';
    // 保存修改后的工作簿
    workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
    // 释放资源
    workbook.Dispose();

    // 从 VFS 读取生成的文件,触发下载
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>替换工作表中的图片</h1>
      <button onClick={replaceImage}>
        替换图片
      </button>
    </div>
  );
}

export default App;

替换图片后的 Excel 工作表效果

替换图片后的 Excel 工作表效果


常见问题

提取的图片无法打开或格式不正确

原因:图片保存时未指定正确的扩展名,或 MIME 类型与图片格式不匹配。

解决:确保 Picture.Save 方法中使用的文件名扩展名与图片实际格式一致。如果是 PNG 格式,文件扩展名应为 .png;如果是 JPEG 格式,则使用 .jpg。下载时 Blob 的 type 也需相应设置:

// PNG 格式
const blob = new Blob([fileArray], { type: "image/png" });

// JPEG 格式
const blob = new Blob([fileArray], { type: "image/jpeg" });

替换图片后位置或大小发生变化

原因:删除原图片前未记录其位置和大小属性,导致新图片无法精确对齐到原始位置或保持原有大小。

解决:在删除前保存图片的 TopRow、LeftColumn、LeftColumnOffset、TopRowOffset 等位置属性以及 Width、Height 大小属性。插入新图片后,通过设置新图片的这些属性使其与原图片保持一致:

// 插入新图片(指定行列位置)
let picture = sheet.Pictures.Add({ topRow: topRow, leftColumn: leftColumn, fileName: newImageFile });

// 设置大小与偏移,与原图片保持一致
picture.Width = width;
picture.Height = height;
picture.LeftColumnOffset = leftColumnOffset;
picture.TopRowOffset = topRowOffset;

获取免费许可证

如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。

我们很高兴宣布发布 Spire.Presentation for .NET 11.8.2。本次更新主要修复了将 PPTX 转换为 PDF 和 SVG 时出现的问题。详情如下。

问题修复:


获取 Spire.Presentation 11.8.2 请点击:

https://www.e-iceblue.cn/Downloads/Spire-Presentation-NET.html

Spire.PDF for Android via Java 10.8.5 现已正式发布。该版本新增支持使用 SHA-256/SHA-512 算法证书对 PDF 文档进行签名。详情如下。

新功能:


获取 Spire.PDF for Android via Java 10.8.5 请点击:

https://www.e-iceblue.cn/Downloads/pdf-for-android-via-java.html

对许多 Web 应用程序而言,文档处理能力直接关系到用户的工作效率,尤其在报告生成和数据整理等场景中。React 依托其基于组件的设计理念,为前端开发提供了理想的支撑。通过集成 Spire.PDF for JavaScript,您可以在 React 应用程序中轻松创建和管理 PDF 文档。

本指南将逐步介绍如何将 Spire.PDF for JavaScript 集成到您的 React 项目中,涵盖环境搭建和使用示例。


在 React 中使用 Spire.PDF for JavaScript 的优势

React 以组件化方式构建用户界面,是现代 Web 开发的主流选择。Spire.PDF for JavaScript 为 Web 应用提供开箱即用的 PDF 处理能力,两者的结合让您在浏览器中即可完成文档的创建、编辑与导出。

将 Spire.PDF for JavaScript 集成到 React 项目中,可以:

  • 提升开发效率:无需后端服务或第三方工具,在前端直接生成和修改 PDF 文档。
  • 扩大使用范围:生成的标准 PDF 文档可跨设备、跨平台流转,便于分发和协作。
  • 覆盖多样需求:文本绘制、图像插入、页面管理等功能一应俱全,满足绝大多数文档场景。
  • 降低集成成本:与 React 等主流框架无缝配合,可快速接入现有项目而不干扰既有流程。

设置开发环境

步骤 1. 安装 React 和 npm

从官方网站下载并安装 Node.js。请确保选择与您的操作系统相匹配的版本。

安装完成后,您可以在终端中运行以下命令来验证 Node.js 和 npm 是否正常工作:

检查 node.js 和 npm 的版本

步骤 2. 创建一个新的 React 项目

在终端中使用 Create React App 创建一个名为 my-app 的新 React 项目:

npx create-react-app my-app

创建 React 项目

如果您的 React 项目编译成功,应用程序将在 http://localhost:3000 上运行,您可以在浏览器中查看和测试您的应用程序。

React 应用程序在 localhost 3000 端口打开

要直观地浏览和管理项目中的文件,您可以使用 VS Code 打开该项目。

在 VS Code 中打开 React 项目


在项目中集成 Spire.PDF for JavaScript

从我们的网站下载 Spire.PDF for JavaScript,并将其解压到磁盘上的某个位置。下载的产品包集成了 Spire.Doc for JavaScript、Spire.XLS for JavaScript、Spire.PDF for JavaScript 和 Spire.Presentation for JavaScript。要使用 Spire.PDF for JavaScript 的功能,您需要将相应的文件(spire.pdf.js、Spire.Pdf.Wasm.zip、spire.common.js、Spire.Common.Wasm.zip 以及 _framework 文件夹)复制到项目的 public 文件夹中。

下载 Spire.PDF for JavaScript 库

您也可以使用 npm 进行安装。在 VS Code 的终端中运行以下命令:

npm i spire.office

安装完成后,产品包文件将保存在项目的 node_modules/spire.office 路径中。将上面提到的 5 个文件复制到 React 项目的 "public" 文件夹中。

为了确保文本正确渲染,您可以通过自定义路径添加相关的字体文件。在以下示例中,字体被添加到路径:public\。

通过 npm 安装的库文件


使用 JavaScript 创建 PDF 文件

修改 App.js 文件中的代码,使用 WebAssembly(WASM)模块生成 PDF 文件。文档的创建与导出操作由 Spire.PDF for JavaScript 库完成。

修改 app.js 文件

以下是完整代码:

import React, { useState, useEffect } from 'react';

function App() {
  const [wasmModule, setWasmModule] = useState(null);
  // 加载 Spire.PDF
  useEffect(() => {
    (async () => {
      try {
        const publicUrl = process.env.PUBLIC_URL || '';
        const spireModule = await import(/* webpackIgnore: true */ `${publicUrl}/spire.pdf.js`);
        const rawModule = spireModule.default || spireModule;
        window.wasmModule = typeof rawModule === 'function'
          ? await rawModule({ locateFile: p => p.endsWith('.wasm') ? `${publicUrl}/${p}` : p })
          : rawModule;
        setWasmModule(window.wasmModule);
      } catch (error) {
        console.error('加载 spire.pdf.js WASM 模块失败:', error);
      }
    })();
  }, []);

  // 生成 PDF 文件的函数
  const createPdf = async () => {
    const pdfModule = window.wasmModule?.spirepdf;
    if (pdfModule) {

      // 将 arial.ttf 字体文件加载到虚拟文件系统(VFS)中
      await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/`);

      // 指定输出文件名
      const outputFileName = 'HelloWorld.pdf';

      // 创建一个新的 PDF 文档
      const doc = new pdfModule.PdfDocument();

      // 添加一页
      let page = doc.Pages.Add();

      // 创建字体和画刷
      let font = new pdfModule.PdfTrueTypeFont({
        fontFamily: 'Arial',
        size: 12,
        style: pdfModule.PdfFontStyle.Regular,
        unicode:true
      });

      let brush = new pdfModule.PdfSolidBrush({pdfRGBColor: new pdfModule.PdfRGBColor({color: pdfModule.Color.get_Blue()})});

      // 在页面的指定位置绘制文本
      page.Canvas.DrawString({ s: "Hello World!", font: font, brush: brush, x: 20, y: 30 });

      // 将文档保存为 PDF 文件
      doc.SaveToFile({ fileName: outputFileName, fileFormat: pdfModule.FileFormat.PDF });

      // 读取保存的文件并将其转换为 Blob 对象
      const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
      const modifiedFile = new Blob([modifiedFileArray], { type: 'application/pdf' });

      // 为 Blob 创建 URL 并启动下载
      const url = URL.createObjectURL(modifiedFile);
      const a = document.createElement('a');
      a.href = url;
      a.download = outputFileName;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);

      // 清理资源
      doc.Close();
    }
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>在 React 中使用 JavaScript 创建 PDF 文件</h1>
      <button onClick={createPdf} disabled={!wasmModule}>
        生成
      </button>
    </div>
  );
}

export default App;

通过在 VS Code 的终端中输入以下命令来启动开发服务器:

npm start

React 应用程序编译成功后,它将在您的默认浏览器中打开,通常地址为 http://localhost:3000。点击"生成"按钮即可创建并下载 "HelloWorld.pdf" 文件。

React 应用程序在本地主机 3000 端口打开


获取免费许可证

如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。

Spire.Barcode 7.5.4 现已发布。该版本同步了 BarcodeSettings 枚举设置到 NETStandard 平台,并且还提升优化了条码识别准确度。详情请查阅以下内容。

新功能:

问题修复:


获取Spire.Barcode 7.5.4 请点击:

https://www.e-iceblue.cn/Downloads/Spire-Barcode-NET.html

Spire.PDF 12.8.0 现已正式发布。该版本成功修复了添加附件失败、PdfGrayConverter.ToGrayPdf() 效果不正确以及提取图片效果不正确的问题。更多详情如下。

问题修复:


获取 Spire.PDF 12.8.0 请点击:

https://www.e-iceblue.cn/Downloads/Spire-PDF-NET.html

Spire.Doc 14.8.0 现已发布。该版本增强了 Word 到 PDF 的转换功能,并修复了获取段落布局元素时抛出“NullReferenceException”异常的问题。详情如下。

问题修复:


获取 Spire.Doc 14.8.0 请点击:

https://www.e-iceblue.cn/Downloads/Spire-Doc-NET.html