Spire.PDF for Python 11.11.0 现已发布。本次更新将自定义的日期处理实现替换为 Python 内置的 datetime 库,以确保在 Python 应用程序中获得更好的兼容性、一致性和可靠性。详细更新内容如下。
调整:
Spire.XLS for Java 15.11.3 现已发布。该版本支持Excel与Markdown格式相互转换,并支持设置文本框段落从右向左。此外,一些转换 Excel 到 PDF、HTML和合并Excel文档时出现的问题也已成功被修复。详情查看下文。
新功能:
//Markdown 转 Excel
Workbook workbook=new Workbook();
workbook.loadFromMarkdown(inputFile);
workbook.saveToFile("out.xlsx", FileFormat.Version2013);
//Excel 转 Markdown
Workbook workbook=new Workbook();
workbook.loadFromFile("in.xlsx");
workbook.saveToFile("out.md", FileFormat.Markdown);
workbook.dispose();
Workbook workbook = new Workbook();
Worksheet sheet = workbook.getWorksheets().get(0);
XlsTextBoxShape textbox = (XlsTextBoxShape) sheet.getTextBoxes().addTextBox(4, 2, 100, 300);
textbox.setText("مبرمج , اختبار .");
textbox.setHAlignment(CommentHAlignType.Left);
textbox.setInnerLeftMargin(1);
textbox.setInnerRightMargin(3);
textbox.setInnerTopMargin(1);
textbox.setInnerBottomMargin(1);
textbox.setTextDirection(TextDirectionType.RightToLeft);
String result = "setInternalMarginOfTextbox_result.xlsx";
workbook.saveToFile(result, ExcelVersion.Version2013);
Workbook workbook = new Workbook();
workbook.loadFromFile("input.xlsx");
Worksheet sheet = workbook.getWorksheets().get(0);
HTMLOptions options = new HTMLOptions();
options.setImageEmbedded(true);
//Setting "HTMLOptions.StyleDefineType.Inline"
options.setStyleDefine(HTMLOptions.StyleDefineType.Inline);
sheet.saveToHtml("out.html",options);
问题修复:
Spire.Presentation 10.11.4 已正式发布。该版本针对 PowerPoint 和 ODP 文件转换为 PDF 的功能进行了重点优化,修复了图片效果显示不正确、布局不一致以及页脚内容丢失等问题。具体更新内容如下:
问题修复:
https://www.e-iceblue.cn/Downloads/Spire-Presentation-NET.html
Spire.PDF for Java 11.11.11 现已发布。本次更新增强了 PDF 到 OFD 和 PDFA 的转换功能,同时修复了多项 PDF 渲染、转换及性能相关的问题,进一步提升了库的稳定性和效率。详情如下:
问题修复:
Spire.XLS for Python 15.11.1 现已发布,该版本新增了 RemoveDuplicates 方法,可自动删除工作表中的重复行,并修复了多个已知问题。更多详情如下。
新功能:
workbook = Workbook()
workbook.LoadFromFile(inputFile)
sheet = workbook.Worksheets[0]
sheet.RemoveDuplicates()
workbook.SaveToFile(outputFile, FileFormat.Version2013)
workbook.Dispose()
问题修复:
本文将详细介绍如何将 Spire.OfficeJS 集成到前端框架 Vue(基于 Vue3 + Vite)中,实现在线打开、预览及编辑 Office 文档的 Web 应用。
通过本教程,你将学会如何:
文章目录
Spire.OfficeJS 是一款基于 Web 的在线 Office 文档编辑产品,包含 Spire.WordJS、Spire.ExcelJS、Spire.PresentationJS、Spire.PDFJS四个模块,提供文档(Word)、电子表格(Excel)、演示文稿(PowerPoint)等格式的查看与实时编辑能力。它可以直接运行在浏览器中,支持部署在任何 Web 项目中,无需安装插件或依赖客户端软件。
适用于企业后台系统、文档管理系统(DMS)、协作平台、在线课程系统、表单系统等多种场景。
请从 Node.js 官网下载并安装版本 22.12.0 或更高版本。安装完成后,通过命令验证环境:
node -v
npm -v

步骤1. 创建一个文件夹
选择一个位置创建新文件夹以存放项目文件。
步骤2. 通过 CMD 进入该文件夹
cd /d d:\demo

步骤3. 初始化 Vue 项目
创建 Vue3 项目并更改项目名称为 vue-spire:
npm init vue@latest

跳过其他设置,完成空白的 Vue 项目创建。

步骤4. 进入项目文件夹并启动服务
cd vue-spire
npm run dev

步骤1. 下载产品包
下载 Spire.OfficeJS 产品包,解压后可看到一个包含编辑器静态资源的 web 文件夹。

步骤2. 复制静态资源到 Public 目录
使用 VS Code 打开你的 Vue 项目,在 public 目录下创建 spire.cloud 文件夹,并将产品包中的 web 文件夹复制到该目录下。这样,在浏览器中可以通过 /spire.cloud/web/... 访问编辑器资源。

步骤3. 安装必要依赖 Pinia 与 Vue Router
使用 VS Code 终端命令行安装 pinia 依赖和 vue-router@4 路由:
npm install pinia
npm install vue-router@4

步骤4. 创建项目结构
在 src 下创建如下目录与文件:
src/
├── router/
│ ├── index.js
├── stores/
│ ├── file.js
├── views/
│ ├── FileUpload.vue
│ └── Spire.OfficeJS.vue

本文件负责初始化整个 Vue 应用,包括:
import { createApp } from'vue'
import { createPinia } from'pinia'
import App from'./App.vue'
import router from'./router'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.use(router)
app.mount('#app')
App.vue 是整个项目的根组件,通常只包含一个路由占位符 <router-view>。
<script setup>
import { RouterView } from 'vue-router'
</script>
<template>
<RouterView/>
</template>
说明:
<router-view> 动态加载定义页面路径,例如:
import { createRouter, createWebHistory } from'vue-router'
import FileUpload from'../views/FileUpload.vue'
import SpireOfficeJs from'../views/Spire.OfficeJs.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'upload',
component: FileUpload
},
{
path: '/document',
name: 'document',
component: SpireOfficeJs
},
{
path: '/:pathMatch(.*)*',
redirect: '/'
}
]
})
export default router
说明:
该 Store 用于保存:
import { ref } from'vue'
import { defineStore } from'pinia'
exportconst useFileStore = defineStore('file', () => {
let file = ref(null)
let fileUint8Data = ref(null);
functionsetFileData(data) {
file.value = data;
}
functionsetFileUint8Data(data) {
fileUint8Data.value = data;
}
return { file, fileUint8Data, setFileData, setFileUint8Data }
})
说明:
用户选择文件后:
<template>
<main>
<label>
<span>选择文件上传</span>
<inputtype="file" @change="handleFileChange" />
</label>
</main>
</template>
<scriptsetup>
import { useRouter } from'vue-router'
import { useFileStore } from'../stores/file'
const router = useRouter()
const fileStore = useFileStore()
asyncfunctionhandleFileChange(event) {
const selectedFile = event.target.files?.[0]
if (!selectedFile) {
return
}
fileStore.setFileData(selectedFile)
const buffer = await selectedFile.arrayBuffer()
fileStore.setFileUint8Data(newUint8Array(buffer))
router.push('/document')
}
</script>
说明:
核心功能:
<template>
<div class="form">
<div id="iframeEditor">
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { storeToRefs } from 'pinia';
import { useFileStore } from '../stores/file.js'
import { useRouter } from 'vue-router';
const fileStore = useFileStore()
// Pinia 中当存储的数据
const { file, fileUint8Data } = storeToRefs(fileStore)
const router = useRouter()
const config = ref({});
const isOpened = ref(false);
const editorInstance = ref(null);
const apiInstance = ref(null);
const originUrl = window.location.origin
onMounted(() => {
// 没有文件时直接跳回上传页
if (!file.value) {
router.replace('/');
return;
}
// 使用script的方式载入
loadScript();
window.addEventListener('resize', OnWindowReSize);
})
onUnmounted(() => {
window.removeEventListener('resize', OnWindowReSize);
})
// 初始化编辑器所需的配置对象
function initConfig() {
if (!file.value) {
throw new Error('未找到文件,请重新上传');
}
if (!fileUint8Data.value) {
throw new Error('未找到文件数据,请重新上传');
}
config.value = {
"fileAttrs": {
"fileInfo": {
"name": file.value.name,
"ext": getFileExtension(),
"primary": String(new Date().getTime()),
"creator": "Jonn",
"createTime": "2022-04-18 11:30:43"
},
"sourceUrl": originUrl + "/files/__ffff_192.168.2.134/" + file.value.name,
"createUrl": originUrl + "/open",
"mergeFolderUrl": "",
"fileChoiceUrl": "",
"templates": {}
},
"user": {
"id": "uid-1",
"name": "Jonn",
"canSave": true,
},
"editorAttrs": {
"editorMode": "edit", //edit / view
"editorWidth": "100%",
"editorHeight": "100%",
"editorType": "document",
"platform": "desktop", //desktop / mobile / embedded
"viewLanguage": "zh", //en / zh
"isReadOnly": false,
"canChat": true,
"canComment": true,
"canReview": true,
"canDownload": true,
"canEdit": true,
"canForcesave": true,
"embedded": {
"saveUrl": "",
"embedUrl": "",
"shareUrl": "",
"toolbarDocked": "top"
},
"useWebAssemblyDoc": true,
"useWebAssemblyExcel": true,
"useWebAssemblyPpt": true,
"spireDocJsLicense": "",
"spireXlsJsLicense": "",
"spirePresentationJsLicense": "",
"spirePdfJsLicense": "",
"serverless": {
"useServerless": true,
"baseUrl": originUrl,
"fileData": fileUint8Data.value,
},
"events": {
"onSave": onFileSave
},
"plugins": {
"pluginsData": []
}
}
};
}
// 创建并渲染 SpireCloudEditor 实例
function initEditor() {
let iframeId = 'iframeEditor';
initConfig();
isOpened.value = true;
editorInstance.value = new SpireCloudEditor.OpenApi(iframeId, config.value); // 创建编辑器实例
window.Api = apiInstance.value = editorInstance.value.GetOpenApi(); // 暴露 OpenApi 便于调试/保存
OnWindowReSize();
}
// 获取上传文件的扩展名,用于配置 fileInfo.ext
function getFileExtension() {
const filename = file.value.name.split(/[\\/]/).pop();
// 获取最后一个点后的内容
return filename.substring(filename.lastIndexOf('.') + 1).toLowerCase() || '';
}
// 调整编辑器容器尺寸,使其随窗口大小自适应
function OnWindowReSize() {
let wrapEl = document.getElementsByClassName("form");
if (wrapEl.length) {
wrapEl[0].style.height = screen.availHeight + "px";
window.scrollTo(0, -1);
wrapEl[0].style.height = window.innerHeight + "px";
}
}
// 动态加载 SpireCloudEditor 脚本,避免重复注入
function loadScript() {
if (window.SpireCloudEditor) {
initEditor()
return
}
const script = document.createElement('script');
script.setAttribute('src', '/spire.cloud/web/editors/spireapi/SpireCloudEditor.js');
script.onload = () => initEditor()
document.head.appendChild(script);
}
// Spire 编辑器的保存回调,可接入自定义保存逻辑
function onFileSave(data) {
console.log('save data', data)
}
</script>
<style>
.form,
iframe,
body {
min-height: 100vh !important;
min-width: 100vh !important;
}
</style>
说明:
在 VS Code 终端输入:
npm run dev

在浏览器输入 http://localhost:5173/(默认),并上传文档。

上传文档后,即可在 Web 页面使用 Spire.OfficeJS 实现在线编辑。

Q1. 编辑器加载失败,页面空白?
可能原因如下:
Q2. 上传文件后跳转到编辑器但无法打开?
请检查:
Q3. 支持哪些文件格式?
常见格式包括:
Q4. 能否实现自定义保存?
可以,通过配置:
events: {
onSave: onFileSave
}
你可以将 data 传给后端 API,实现真正的文件持久化。
Q5. 可以部署到生产服务器吗?
可以,部署时需确保:
如果您需要去除生成文档中的评估提示或解除功能限制,请联系我们获取有效期 30 天的临时许可证。
Spire.Doc 13.11.5 现已发布。该版本优化了OfficeMath处理,提升了公式展示效果。详情如下
调整:
Spire.PDF 11.11.5 现已发布。该版本重点修复了 PDF 转换相关问题,包括 PDF 转 PDF/A、PDF 转图片、打印效果、水印表现、OFD 转换以及部分异常错误。同时,还优化了 NetStandard DLL 转图片的性能,进一步提升了产品的稳定性与处理效率。详情如下:
问题修复:
Spire.Presentation for Java 10.11.4 现已发布。本次更新主要针对跨平台使用场景提升稳定性,修复了在 ColdFusion 平台调用组件时出现 NullReferenceException 的问题,从而增强了整体兼容性与可靠性。更新详情如下:
问题修复:
https://www.e-iceblue.cn/Downloads/Spire-Presentation-JAVA.html
Spire.Presentation for Python 10.11.1 已发布,本次更新主要修复了在将 PowerPoint 文件转换为图片时出现的问题。具体更新内容如下。
问题修复:
https://www.e-iceblue.cn/Downloads/Spire-Presentation-Python.html