技術方案背景:根據項目需要,要實現在線查看、在線編輯文檔,并且進行內容的快速回填,根據這一項目背景,最終采用WPS的API來實現,接下來我們一起來實現項目功能。
1.首先需要先準備好測試使用的文檔,并且做好標簽節點的標記,在要需要回填的地地方打好標記標簽
打開文檔 => 點擊菜單欄插入 => 找到要添加書簽的地方,選擇工具欄的書簽按鈕
輸入對應的命名書簽
表格書簽是打標記在表格內容上方,便于查找表格位置方便替換;
2. 引入WPS Web Office SDK代碼示例(vue項目舉例,在根目錄下的index.html文件中引入)
<script src="/wps-sdk/web-office-sdk-solution-v2.0.7.umd.js"></script>
注意事項
SDK路徑需要根據實際存放位置調整,若使用CDN方式可替換為完整URL
當前示例使用的是v2.0.7版本的UMD格式SDK,適用于大多數瀏覽器環境
建議將腳本放在<head>
標簽內或<body>
標簽末尾,避免阻塞頁面渲染
初始化示例
const config = {mount: document.getElementById('office-container'),url: 'https://example.com/test.docx'
};
WebOfficeSDK.initialize(config);
版本選擇建議
生產環境建議鎖定具體版本號(如示例中的v2.0.7)
測試環境可使用最新版本,但需注意API兼容性
UMD格式適用于傳統網頁開發,若使用模塊化開發可考慮ES模塊版本
以上代碼需配合WPS官方文檔使用,確保初始化參數配置正確(WPS官方文檔:快速上手 | WPS WebOffice 開放平臺)
3.使用HTML代碼塊編寫的WPS文檔在線查看容器代碼:
<!-- 創建wps文檔在線查看容器 -->
<div id="wps-frame" class="w-full h-[calc(100%-60px)] bg-#eee custom-mount"></div>
代碼說明
該代碼創建了一個具有以下特性的div容器:
- 使用
id="wps-frame"
作為唯一標識 - 通過
class
屬性應用了多個樣式:w-full
:寬度100%h-[calc(100%-60px)]
:高度為總高度減去60pxbg-#eee
:背景色設置為淺灰色custom-mount
:預留的自定義掛載類名
樣式補充建議
如需更精確控制樣式,可以添加CSS:
#wps-frame {border: 1px solid #ddd;margin: 0 auto;overflow: hidden;
}
4. 初始化WPS容器
const init = async () => {window.fileurlType = props.fileObj.fileurl.split('.').pop().toLowerCase();instance = WebOfficeSDK.init({//文檔類型officeType: window.fileurlType === 'xlsx' || window.fileurlType === 'xls' ? WebOfficeSDK.OfficeType.Spreadsheet : window.fileurlType === 'docx' || window.fileurlType === 'doc' ? WebOfficeSDK.OfficeType.Writer : WebOfficeSDK.OfficeType.Otl,appId: "你申請的預覽服務的appid",fileId: props.fileObj.fileid,token: token,mount: document.getElementById('wps-frame'),mode: props.submitType === true ? 'nomal' : 'simple',});//如果props.submitType為true,則設置為可以編輯 否則設置為只讀if (props.submitType == false) {await instance.ready();const app = instance.Application;await app.ActiveDocument.SetReadOnly({Value: true});} else {await instance.ready();//根據接口返回信息對文檔進行回填getInformationBackfilling();}
}
5. 容器初始化后我們拿到需要回填的數據就可以進行數據回填操作
//根據接口返回信息對文檔進行回填
const getInformationBackfilling = () => {detailObj(props.fileObj?.projectid || props.projectid ).then(res => {const { data } = res//解析JSON格式的回填數據const recruitcontent = JSON.parse(data.recruitcontent)//保存預設的書簽內容的回填信息,字段需要對應在文檔中打的標記書簽allData.value = {projectname: data.projectname,projectcode: data.projectcode,recrunit: data.recrunit,abbreviation: data.projectname,}// 執行書簽回顯業務setBookmarks()// 獲取表格回顯內容const list = recruitcontent.map((item, index) => {item.indexNumber = index + 1item.projectName = data.projectnameitem.subProjectDl = ""return item})// 執行表格回顯業務addTable(list, 1)})
}
6. 書簽回顯業務
//書簽賦值
const setBookmarks = async () => {const app = instance.Application;// 書簽對象const bookmarks = await app.ActiveDocument.Bookmarks;let replaceArr = [];needSet.forEach((item) => {let { key } = getKey(item.name);replaceArr.push({name: item.name,type: 'text',value: allDataInfo.value[key]?.toString(),});});// 替換書簽內容const isReplaceSuccess = await bookmarks.ReplaceBookmark(replaceArr);
}
7. 表格回顯業務
//插入表格(標的物)
const addTable = async (list, type) => {if (!list && list?.length == 0) return;const app = instance.Application;let tabelHeade = [{title: '序號',key: 'indexNumber',},{title: '項目名稱',key: 'projectName',},{title: '子目名稱',key: 'subProjectName',},{title: '技術服務內容',key: 'techServiceContent',},{title: '單位',key: 'unit',},{title: '數量',key: 'quantity',},{title: '備注',key: 'remark',},];const tables = await app.ActiveDocument.Tables;// 等待表格創建完成await new Promise(resolve => {const interval = setInterval(async () => {const currentCount = await tables.Count;if (currentCount >= 10) {clearInterval(interval);resolve();}}, 300);});setTimeout(async () => {// 獲取頁面中總表格數量const count = await tables.Count;const Bookmark = await app.ActiveDocument.Bookmarks.Item('定義的表格書簽名');// 插入表格await tables.Add(Bookmark.Range, // 位置信息list.length + 1, // 新增表格的行數tabelHeade.length, // 新增表格的列數1,2,);const tableOne = await tables.Item(Bookmark);for (let i = 0; i < list.length + 1; i++) {for (let j = 0; j < tabelHeade.length; j++) {const curCell = await tableOne.Rows.Item(i + 1).Cells.Item(j + 1);const rowText = await curCell.Range;// 設置單元格內容的字號const font = await rowText.Font;font.Size = 12; // 設置字號為 12rowText.Text = i == 0 ? tabelHeade[j].title : list[i - 1][tabelHeade[j].key] ? list[i - 1][tabelHeade[j].key].toString() : "";}}}, 1000 * 1.5);};
8. 擴展內容合并單元格
// 合并行表格單元格 instance:WebOfficeSDK初始化的文檔容器,tableIndex:表格編號, rowIndex:開始行,startColIndex:結束行 , value: 替換值)
async function mergeTableCells(instance, tableIndex, rowIndex, startColIndex, endColIndex, value) {const app = instance.Application;const doc = app.ActiveDocument;const tables = await doc.Tables;// 獲取指定表格const table = await tables.Item(tableIndex);// 獲取指定行const row = await table.Rows.Item(rowIndex);// 獲取起始單元格和結束單元格const startCell = await row.Cells.Item(startColIndex);const endCell = await row.Cells.Item(endColIndex);// 合并單元格await startCell.Merge(endCell);// 設置合并后單元格的值const mergedCell = await row.Cells.Item(startColIndex);const mergedCellRange = await mergedCell.Range;mergedCellRange.Text = value;
}// 合并列表格單元格(instance:WebOfficeSDK初始化的文檔容器,tableIndex:表格編號, startRowIndex:開始列,endRowIndex:結束列, value: 替換值 )
async function mergeFirstColumnRows(instance, tableIndex, startRowIndex, endRowIndex, value) {const app = instance.Application;const doc = app.ActiveDocument;const tables = await doc.Tables;// 獲取指定表格const table = await tables.Item(tableIndex);// 獲取起始行和結束行const startRow = await table.Rows.Item(startRowIndex);const endRow = await table.Rows.Item(endRowIndex);// 獲取第一列的起始單元格和結束單元格const startCell = await startRow.Cells.Item(1);const endCell = await endRow.Cells.Item(1);// 合并單元格await startCell.Merge(endCell);// 設置合并后單元格的值const mergedCell = await table.Rows.Item(startRowIndex).Cells.Item(1);const mergedCellRange = await mergedCell.Range;mergedCellRange.Text = value;
}
小結:
1. 根據業務需求,首先初始化時,實現了文檔在線查看的功能,根據是否需要編輯的狀態設置文檔只讀模式或者編輯模式;
2. 實現回填功能中,根據拿到的需要回填的數據做處理對應給需要回填的書簽內容區域
3. 回填表格功能,根據表頭配置好對應回顯字段,進行業務回填,增加擴展功能對表格中部分地方單元格合并的方法;
功能代碼是已實現的業務邏輯,中間也踩坑不少,最終實現文檔在線查看,在線編輯以及文本和表格回填功能,歡迎大家多多交流溝通,提出建議,指出錯誤,我們一起成長,最后希望大家在踩坑路上繼續成長。