
# 1 功能介绍
支持word、excel文档的在线编辑、保存、模板变量定义和替换等操作,Office文档和金蝶云苍穹实现无缝对接。
# 2 控件对象
`kd.bos.form.control.WebOffice`
# 3 视觉展示
Demo见附件

# 4 安装和环境配置
## 4.1 下载安装weboffice组件
安装包见附件,建议安装到C盘或D盘根目录下,安装路径不要包含中文。
## 4.2 配置本地环境
需预先安装IE浏览器(11.0及以上)以及Office、WPS办公软件(支持Office2003,Office2007,Office2010,Office2013, Office2016等非Home版、非Student版的办公软件,支持Office的32位和64位,必须是完全安装的版本,Ghost版系统自带Office的话,需要卸载重装Office),不支持苹果操作系统。
# 5 API及指令
## 5.1 Java API
方法名 | 参数 | 说明
:-------: | :-------: | :------:
`save` | `String` 文件名 | 保存文档
`close` | 无 | 关闭文档
`open` | `String` 文档URL | 打开文档
`open` | `String,String` 文档URL,用户名 | 打开文档
`open` | `String,List<String>,String` 文档URL,书签,密码 | 打开文档,仅设定可编辑区域才可供用户修改
`open` | `String,String,List<String>,String` 文档URL,用户名,书签,密码 | 打开文档,仅设定可编辑区域才可供用户修改
`openAll` | `String, String` URL文档,文件名 | 支持打开多种文档包含Excel,需要传入文件名以打开文件
`addTable` | `String[][]` 插入数据 | 添加表格
`addTable` | `String,String[][]` 书签,插入数据 | 指定处添加表格
`setTrackingMode` | `String, WebOfficeTrackingType` 用户名,类型 | 设置留痕模式
`addBookmarkForSelection` | `String` 书签 | 为鼠标选中内容设置为书签
`setTextStyle` | `String,String` 书签名,第二个参数取值:"标题、"引用"等,具体查看word的标题样式名称 | 调整指定书签内容的标题样式
`mergeDocs` | `WebOfficeMergeType, String[]`合并类型,合并文档URL | 合并其他文档至当前文档
`mergeDocsByBookmark` | `String,String[]` 书签,合并文档URL | 合并其他文档至当前文档选中页签处
`addTableColumns` | `String,String[][]` 书签,列数据 | 表格添加列数据
`addTableRows` | `String,String[][]` 书签,行数据 | 表格添加行数据
`setCheckBoxChecked` | `String,String…`是否选中,复选框 | 设置复选框值
`getAllCheckBoxs` | 无 | 获取文档中所有的复选框
`getTextByBookmark` | `String` 书签 | 依据书签获取文档内容
`isDocChanged` | 无 | 获取文档是否有改动
`getAllBookmarks` | 无 | 获取所有书签
`checkBookmark` | `String` 书签 | 查询书签是否存在
`showTracesBy` | `String,boolean` 用户名,是否显示修改痕迹 | 按照用户名是否显示某用户的修改痕迹
`showAllTraces` | `boolean` 是否显示 | 切换显示痕迹
`setEditableAreas` | `List<String>,String`书签,密码 | 设置文档可编辑区域,只有传递标签选中区域才能被当前用户编辑
`setDocUnLimitByRole` | `List<String>` 书签 | 取消文档可编辑区域,可编辑其他区域
`deleteSelectedAreaEditBookmark` | `String` 书签 | 删除编辑标签
`setSelectedAreaEditBookmark` | `String` 书签 | 对选中区域设置可编辑标签
`unLimitDoc` | `String` 密码 | 解除限制文档编辑
`limitDoc` | `String` 密码 | 限制文档编辑
`cancelProtectDoc` | `String` 密码 | 取消文档保护
`protectDoc` | `WebOfficeDocProtectionType, String` 保护类型,密码 | 文档保护
`showCommentDialog` | 无 | 弹出添加批注的框
`locateMark` | `String` 书签 | 定位书签
`deleteMarks` | `List<String>`书签列表 | 删除书签
`modifyMarks` | `List<WebOfficeMark>`书签列表 | 修改书签
`addMarks` | `WebOfficeMark` 书签 | 添加书签
`insertValue` | `String` 值 | 插入值
`insertValue` | `String,boolean` 值,是否换行 | 插入值
`insertPictures` | `List <WebOfficeImage>` | 插入图片, 支持批量操作
`compareFile` | `String,String,String, String` 第一个文档URL,第一个文挡名称,第二个文挡URL,第二个文档名称 | 比较文档
`sendIsFieldRevise` | `String` 书签 | 是否被修订
`setCaption` | `String` 标题 | 插入标题
`setMenubar` | `Boolean`是否显示 | 设置菜单栏是否显示
`setTitlebar` | `Boolean` 是否显示 | 设置标题栏是否显示
`setDocAsField` | `String` 书签 | 设置整个文档内容为书签
`setToolbars` | `Boolean` 是否显示 | 设置工具栏是否显示
`sendOpenStatus` | 无 | 获取文档打开状态
`reportData` | `Map<String,Object>` 数据 | 回调数据
`upload` | `Map<String, Object>` 文档上传成功后的相关信息 | 文档上传成功后上报接口
`afterClose` | `Map<String,Object>` 数据 | 数据发生改变,weboffice浏览器关闭后可触发关闭后事件
`addDataListener` | `WebOfficeDataListener` weboffice前端数据回调事件监听 | 添加前端数据回调事件
`addUploadListener` | `UploadListener` 上传事件监听器 | 添加上传事件
`getDataListeners` | 无 | 获取数据监听器
## 5.2 前端指令
指令名 | 参数 | 返回后端参数 | 说明
:-------: | :-------: | :------: | :------:
`openUrl` | ["WebOffice\:\/\/\|Officectrl\|<https://vip.kingdee.com/>"] | 无 | 打开webOffice控件弹窗并跳转到指定页面
`setCaption` | {"data":{"value":"标题栏文字"}} | 无 | 添加控件标题栏文字
`setTitlebar` | {"data":{"value":true\false}} | 无 | 设置是否显示标题栏
`setToolbars` | {"data":{"value":true\false}} | 无 | 设置是否显示工具栏
`setMenubar` | {"data":{"value":true\false}} | 无 | 设置菜单栏是否显示
`open` | {"data":{"url":"文档url","userName":"用户名","name":"文件名"}} | 无 | 打开Office文档包括(.doc、.docx、.xls、.xlsx),打开前先将本地Office窗口关闭
`openNew` | {"data":{"fileType":"Word.Document"}} | 无 | 新建空白word,excel,ppt文件,fileType可以是"Excel.Sheet","Word.Document","PowerPoint.Show"
`save` | {"data":{"uploadUrl":"上传文件服务器地址(必须是完整url)","name":"文件名称(包含后缀)","id":"事件回调id"}} | 无 | 保存当前文档到服务器(本地文档应先通过附件上传至服务器)
`close` | 无 | 无 | 关闭当前文档
`insertValue` |{"data":{"needEnterBefore":true\false是否需要在插入文本前添加回车换行(可触发office自动编号)}} | 无 | 在光标位置插入文本内容
`insertPictures` | {data: [{imageUrl: "https://example/image.webp", field: "fieldName1", imageStyle: { width: "50px", height: "50px" }}]} | 无 | 在指定位置插入图片,支持批量操作,imageUrl:图片地址;field:必填, 书签名,可选,值为空则在光标位置插入图片;imageStyle:图片宽高,width、height可以是"px"单位或者 "cm"单位, 如:{width:"50px", height:"50px"}(等价于{width:"50", height:"50"})、{width:"5cm", height:"5cm"}
`addCommentDialog` | 无 | 无 | 在光标位置或选中文字处插入批注
`docCompare` | {"data":{"currentFile":"原文档名称.doc",currentFileUrl:"原文档url","compareFile":"比较文档名称.doc","compareFileUrl":"比较文档url"}} | 无 | 文本比较(暂不支持docx格式的文档比较),使用此功能需更改本地Office设置,比较结果会在本地Office打开
`addMark` | {"data":{"field":"书签名称","value":"{变量名称}"}} | 无 | 在光标位置插入一个书签,用于定义模板变量,书签即变量
`deleteMark` | {"data":[{"field":"书签名称1"}, { "field":"书签名称2"}]} | 无 | 删除文档中书签(支持批量删除)
`modifyMark` | {"data":[{"field":"书签名称1", "value":"变量的值1"},{"field":"书签名称2","value":"变量的值2"}]} | 无 | 替换书签的值 (支持批量替换)
`locateMark` | {"data":{"field":"书签名称1"}} | 无 | 定位到某个书签的位置
`mergeDocs` | {"data":{"field":书签名称", "mergeType":0光标位置\1文档开头\2文档结尾\3书签位置, "docsUrl":["文档的url"]}} | 无 | 合并文档,即在指定位置插入文档(原文档和合并文档的书签和复选框合并后仍可用)
`docProtect` | {"data":{"isProtect": 0保护\1解除保护,"protectType":0只允许修订\1只允许添加批注\2完全保护,"password":"文档保护的密码"}} | 无 | isProtect参数设为0时,才能设置文档只允许修订\只允许添加批注\完全保护(不允许任何操作)
`setDocLimit` | {"data":{"password":"密码"}} | 无 | 开启区域限制,开启后文档将被限制编辑,只有允许编辑的区域才能被编辑
`setDocUnLimit` | {"data":{"password":"密码"}} | 无 | 解除区域限制,文档恢复可编辑状态
`setSelectionEditArea` | {"data":{"field":"书签名称"}} | 无 | 设置选中区域为可编辑区域(选中区域将被设置为书签)
`cancelSelectionEditArea` | {"data":{"field":"书签名称"}} | 无 | 取消选中区域的第一个书签内容的编辑状态(对应书签将被删除)
`setDocLimitByRole` | {"data":{"field":["书签名称1", "书签名称2"],"password":"密码"}} | 无 | 批量设置书签内容为可编辑,并开启区域限制,其他区域将被锁定
`setDocUnLimitByRole` | {"data":[{"field":"书签名称1"}, {"field":"书签名称2"}]} | 无 | 批量取消取消书签内容的可编辑状态
`setSelectionAsField` | {"data":{"field":"书签名称"}} | 无 | 设置选中区域内容为书签
`setDocAsField` | {"data":{"field":"书签名称"}} | 无 | 设置整个文档内容为书签
`setTextAsTitle` | {"data":{"field":"书签名称","style":"标题 1"}} | 无 | 设置书签内容为标题1样式
`setCheckBoxValue` | {"data":[{"id":复选框id1,"value":true\false}, {"id":复选框id2,"value":true\false}]} | 无 | 批量修改复选框的值
`setDynamicTable` | {"data":{"field":"书签名称","tableData":[{"row":1,"column":2,"value":"123123"}, {"row":2,"column":2,"value":"123123"}],"tableSize":{"row":3,"column":2}}} | 无 | 在书签位置插入表格(tableData:表格数据,{"row":1,"column":2,"value":"123123"}表示第1行第2列的表格值为123123;tableSize:表格规格,{"row":3,"column":2}}表示表格规格为3行2列)
`addTableColumns` | {"data":{"field":"表格所在的书签名", "newColumns":2, "newRowsData":[["123123" , "123123" ], ["123123" , "123123" ]]}} | 无 | 为指定的表格新增多列数据,需先将表格设为书签,否则默认是第一个表格
`addTableRows` | {"data":{"field":"表格所在的书签名", "newRows":2, "newRowsData":[["123123" , "123123" ], ["123123" , "123123" ]]}} | 无 | 为指定表格新增多行数据,需先将表格设为书签,否则默认是第一个表格
`setTrackingMode` | {"data":{"userName":"","trackType":1开启留痕模式并开始修订\0关闭留痕模式\4接受当前所有修订}} | 无 | 开启强制留痕模式,开启后所有修改痕迹将被记录
`showTracesByRole` | {"data":{userName: "用户名",isShow:true}} | 无 | 按用户名称显示、隐藏修改痕迹
`toggleShowTraces` | 无 | 无 | 切换显示痕迹(显示或隐藏修改痕迹)
`sendTextByField` | {"data":{"field":"书签名称", id:"事件回调id"}} | {"result":"书签的文本内容","field":"书签名称"} | 根据书签名称获取文本内容并发送后端
`sendIsFieldRevise` | {"data":{"field":"书签名称", id:"事件回调id"}} | {"result":true\false,"field":"书签名称"} | 书签内容是否有任意改动(包含样式、批注等),并将结果发给后端
`sendFieldExist` | {"data":{"field":"书签名称", "id":"事件回调id" }} | {"result":true\false,"field":"书签名称"}] | 判断当前书签是否存在,并将结果发送给后端
`sendAllField` | {"data":{"id":"事件回调id" }} | ["书签名称1", "书签名称2"] | 获取当前文档所有书签,并将结果发送给后端
`sendIsDocChange` | {"data":{"id":"事件回调id" }} | true\false | 判断当前文档是否已更改,并将结果发送给后端
`sendAllCheckBox` | {"data":{"id":"事件回调id" }} | [{"id":复选框id, "value":true\false复选框的值, "title":"复选框标题"}] | 查找所有复选框,并将结果发送给后端
`sendOpenStatus` | {"data":{"id":"事件回调id" }} | true\false | 获取当前文档的打开状态,并将结果发送给后端
# 6 接口介绍及使用示例
## 6.1 通用接口介绍及使用示例
### 6.1.1 设置标题栏、工具栏、菜单栏、标题栏说明文字
可以在控件界面展示的相关设置。
```java
//显示标题栏
private void setTitlebar() {
WebOffice webOffice = getControl("webofficeap");
webOffice.setTitlebar(true);
}
//显示工具栏
private void setToolbars() {
WebOffice webOffice = getControl("webofficeap");
webOffice.setToolbars(true);
}
//显示菜单栏
private void setMenubar() {
WebOffice webOffice = getControl("webofficeap");
webOffice.setMenubar(true);
}
//设置标题栏说明文字
private void setCaption() {
Object data = getModel().getValue("txt_msg");
if(null == data){return;}
WebOffice webOffice = getControl("webofficeap");
webOffice.setCaption(data.toString());
}
```
### 6.1.2 打开、保存和关闭
打开、保存和关闭word、excel、ppt等文档的通用接口。
```java
//打开word、Excel、ppt等各种文档
private void openDoc (){
//这里的url可以是通过上传附件后获取到的url,也可以是本地文档url
String url ="D://feature//bos_core//kd_bos//bos//webofficedemo//src//main//resources//docsUrl.xlsx";
WebOffice webOffice = getControl("webofficeap");
/**
* WebOffice 调用openAll方法
* @param url 文件url
* @param fileName 文件名
*/
webOffice.openAll(url, "docsUrl.xlsx");
}
//打开word文档
private void open() {
String url ="D://feature//bos_core//kd_bos//bos//webofficedemo//src//main//resources//docsUrl.docx";
WebOffice webOffice = getControl("webofficeap");
webOffice.open(url);
}
//获取文档打开状态
private void sendOpenStatus() {
WebOffice webOffice = getControl("webofficeap");
webOffice.sendOpenStatus();
}
//文档保存到服务器
private void saveDoc() {
String name = (String)getModel().getValue("name");
if(StringUtils.isBlank(name)){
getView().showErrorNotification("文件名不能为空");
return;
}
WebOffice webOffice = getControl("webofficeap");
webOffice.save(name);
}
//关闭文档
private void open() {
WebOffice webOffice = getControl("webofficeap");
webOffice.close();
}
```
## 6.2 Word文档接口介绍及使用示例
### 6.2.1 模板变量
模板变量是将word文档中的某段内容当成变量,可根据后端数据进行内容的替换。如文档中的设置了内容变量: ${甲方},可根据后端数据将word文档中的 “${甲方}” 替换成某个字段的值,实现模板变量替换的功能。
变量通过插入书签方式实现,每个变量都是一个文档书签,也可将整个文档设为书签。注意: *由于word文档书签功能限制,书签前面的内容修改后将会设置成该书签的一部分,因此不允许在书签前面插入书签或做修改。建议把文档模板编辑完成后再进行变量的插入操作。
```java
/*
*案例说明
*1.制作word模板时,先将模板编辑好,然后在文档中插入变量
*2.重新初始化文档时将文档变量替换成正式内容
*/
//插入书签
private void addMarksTest(){
WebOffice webOffice = getControl("webofficeap");
String name = "name";
String value = "value";
/**
* WebOffice 调用addMarks方法
* @param WebOfficeMark 书签
*/
//插入书签
webOffice.addMarks(new WebOfficeMark(name, value));
}
//变量替换
private void modifyMarksTest(){
WebOffice webOffice = getControl("webofficeap");
//这里是你处理你要修改的书签
DynamicObject tpl = BusinessDataServiceHelper.loadSingle(tplId,"test_wb_doc_templete");
DynamicObjectCollection tplVariables = tpl.getDynamicObjectCollection("entry_variable");
List<WebOfficeMark> marks = new ArrayList<>();
List<WebOfficeMark> marks = new ArrayList<>();
for (DynamicObject variable : tplVariables) {
String map = variable.getString("variable_map");
String key = variable.getString("variable_key");
String value = StringUtil.toSafeString(doc.get(map));
//添加要修改的书签
marks.add(new WebOfficeMark(key,value));
}
/**
* WebOffice 调用modifyMarks方法
* @param List<WebOfficeMark> 修改的书签
*/
webOffice.modifyMarks (marks);
}
//书签定位,实现跳转到文档指定位置
private void locateMark(int rowIndex) {
String markKey = (String)getModel().getValue("doc_key",rowIndex);
WebOffice webOffice = getControl("webofficeap");
webOffice.locateMark(markKey);
}
//删除书签
private void deleteMark(int rowIndex) {
String markKey = (String)getModel().getValue("doc_key",rowIndex);
WebOffice webOffice = getControl("webofficeap");
webOffice.deleteMarks(Arrays.asList(markKey));
getModel().deleteEntryRow("entryentity_doc", rowIndex);
}
//获取所有书签
private void getAllBookmarks() {
WebOffice webOffice = getControl("webofficeap");
webOffice.getAllBookmarks();
}
//检测书签是否存在
private void bookMarkCheck() {
WebOffice webOffice = getControl("webofficeap");
String mark = (String)getModel().getValue("txt_mark");
if(StringUtils.isBlank(mark)){
getView().showErrorNotification("请先录入要插入表格处的书签");
return;
}
webOffice.checkBookmark(mark);
}
//获取当前书签的文本内容
private void getTxt() {
WebOffice webOffice = getControl("webofficeap");
String mark = (String)getModel().getValue("txt_mark");
if(StringUtils.isBlank(mark)){
getView().showErrorNotification("请先录入要插入表格处的书签");
return;
}
webOffice.getTextByBookmark(mark);
}
//将选中内容设为书签
private void addBookmarkForSelection() {
WebOffice webOffice = getControl("webofficeap");
webOffice.addBookmarkForSelection("bookmark");
this.getView().showSuccessNotification("添加书签成功!");
}
//将整个文档设为书签
private void setDocAsField() {
WebOffice webOffice = getControl("webofficeap");
webOffice.setDocAsField("bookMark");
}
//查看书签内容是否存在修改痕迹
private void getFieldRevise() {
WebOffice webOffice = getControl("webofficeap");
String mark = (String)getModel().getValue("txt_mark");
if(StringUtils.isBlank(mark)){
getView().showErrorNotification("请先录入要插入表格处的书签");
return;
}
webOffice.sendIsFieldRevise(mark);
}
```
### 6.2.2 批注
可以在word文档中插入批注。
```java
//插入批注
private void showCommentdialog() {
WebOffice webOffice = getControl("webofficeap");
webOffice.showCommentDialog();
}
```
### 6.2.3 表格
可以在word文档中指定位置动态插入指定行列数的表格,并填充表格数据。可动态修改指定表格数据或行列数,还可以给指定表格新增行列。
将表格设置为书签即可定位到指定的表格,然后对改表格进行相关操作。
```java
//在指定位置位置插入表格并初始化表格数据
private void addTable(String type) {
String[][] tableDatas = {
{"编号","姓名","年龄"},
{"1","张三","18"},
{"2","李四","20"},
{"3","王五","19"}
};
WebOffice webOffice = getControl("webofficeap");
//在书签位置插入表格并初始化表格数据
if("bookmark".equals(type)){
String mark = (String)getModel().getValue("txt_mark");
if(StringUtils.isBlank(mark)){
getView().showErrorNotification("请先录入要插入表格处的书签");
return;
}
webOffice.addTable(tableDatas);
}else{
//在光标位置插入表格并初始化表格数据
webOffice.addTable(tableDatas);
}
}
//为表格增加两列数据
private void addTableColumns() {
WebOffice webOffice = getControl("webofficeap");
String[][] tableDatas = {
{"性别","男","女"},
{"身高","177","155"}
};
webOffice.addTableColumns("bookmark", tableDatas );
}
//为表格增加两行数据
private void addTableRows() {
WebOffice webOffice = getControl("webofficeap");
String[][] tableDatas = {
{"4","李六","18"},
{"5","吴七","18"}