UNPKG

vue-easytable

Version:
429 lines (367 loc) 11.5 kB
const regUniversalNewLine = /^(\r\n|\n\r|\r|\n)/; const regNextCellNoQuotes = /^[^\t\r\n]+/; const regNextEmptyCell = /^\t/; /** * @decodeSpreadsheetStr * @desc Decode spreadsheet string into array. refer from http://github.com/warpech/sheetclip/ * @param {string} str The string to parse. * @returns {array} */ export function decodeSpreadsheetStr(str) { let arr = [[""]]; if (str.length === 0) { return arr; } let column = 0; let row = 0; let lastLength; while (str.length > 0) { if (lastLength === str.length) { // In the case If in last cycle we didn't match anything, we have to leave the infinite loop break; } lastLength = str.length; if (str.match(regNextEmptyCell)) { str = str.replace(regNextEmptyCell, ""); column += 1; arr[row][column] = ""; } else if (str.match(regUniversalNewLine)) { str = str.replace(regUniversalNewLine, ""); column = 0; row += 1; arr[row] = [""]; } else { let nextCell = ""; if (str.startsWith('"')) { let quoteNo = 0; let isStillCell = true; while (isStillCell) { const nextChar = str.slice(0, 1); if (nextChar === '"') { quoteNo += 1; } nextCell += nextChar; str = str.slice(1); if ( str.length === 0 || (str.match(/^[\t\r\n]/) && quoteNo % 2 === 0) ) { isStillCell = false; } } nextCell = nextCell .replace(/^"/, "") .replace(/"$/, "") .replace(/["]*/g, (match) => new Array(Math.floor(match.length / 2)) .fill('"') .join(""), ); } else { const matchedText = str.match(regNextCellNoQuotes); nextCell = matchedText ? matchedText[0] : ""; str = str.slice(nextCell.length); } arr[row][column] = nextCell; } } // 去除 excel 最后一个多余的换行数据 if (Array.isArray(arr) && arr.length > 1) { if (arr[arr.length - 1].length === 1 && arr[arr.length - 1][0] === "") { arr = arr.slice(0, arr.length - 1); } } return arr; } /** * @decodeSpreadsheetStr * @desc encode array to spreadsheet string. refer from http://github.com/warpech/sheetclip/ * @param {array} str The string to parse. * @returns {string} */ export function encodeToSpreadsheetStr(arr) { let r; let rLen; let c; let cLen; let str = ""; let val; for (r = 0, rLen = arr.length; r < rLen; r += 1) { cLen = arr[r].length; for (c = 0; c < cLen; c += 1) { if (c > 0) { str += "\t"; } val = arr[r][c]; if (typeof val === "string") { if (val.indexOf("\n") > -1) { str += `"${val.replace(/"/g, '""')}"`; } else { str += val; } } else if (val === null || val === void 0) { // void 0 resolves to undefined str += ""; } else { str += val; } } if (r !== rLen - 1) { str += "\n"; } } return str; } /** * @onBeforeCopy * @desc on before copy * @param {Event} event * @return {selectionRangeIndexes,selectionRangeKeys,data} */ export function onBeforeCopy({ cellSelectionRangeData, selectionRangeData, colgroups, allRowKeys, }) { const { leftColKey, rightColKey, topRowKey, bottomRowKey } = cellSelectionRangeData; const selectionRangeIndexes = { startColIndex: colgroups.findIndex((x) => x.key === leftColKey), endColIndex: colgroups.findIndex((x) => x.key === rightColKey), startRowIndex: allRowKeys.indexOf(topRowKey), endRowIndex: allRowKeys.indexOf(bottomRowKey), }; const selectionRangeKeys = { startColKey: leftColKey, endColKey: rightColKey, startRowKey: topRowKey, endRowKey: bottomRowKey, }; const response = { selectionRangeIndexes, selectionRangeKeys, data: selectionRangeData, }; return response; } /** * @onAfterCopy * @desc on after copy * @param {Event} event * @return */ export function onAfterCopy({ event, selectionRangeData }) { const spreadsheetStr = encodeToSpreadsheetStr(selectionRangeData); if (event.clipboardData) { event.clipboardData.setData("text/plain", spreadsheetStr); } // IE browser else if (window.clipboardData) { window.clipboardData.setData("Text", spreadsheetStr); } } /** * @onBeforePaste * @desc on before paste * @param {Event} event * @return */ export function onBeforePaste({ event, cellSelectionRangeData, colgroups, allRowKeys, }) { let pastedData; if (event.clipboardData) { pastedData = event.clipboardData.getData("text/plain"); } // IE browser else if (window.clipboardData) { pastedData = window.clipboardData.getData("Text"); } if (typeof pastedData !== "string") { return null; } let decodePasteData = decodeSpreadsheetStr(pastedData); const startColIndex = colgroups.findIndex( (x) => x.key === cellSelectionRangeData.leftColKey, ); const endColIndex = Math.min( startColIndex + decodePasteData[0].length - 1, colgroups.length - 1, ); const startRowIndex = allRowKeys.indexOf(cellSelectionRangeData.topRowKey); const endRowIndex = Math.min( startRowIndex + decodePasteData.length - 1, allRowKeys.length - 1, ); let response = { selectionRangeIndexes: { startColIndex, endColIndex, startRowIndex, endRowIndex, }, selectionRangeKeys: { startColKey: colgroups[startColIndex].key, endColKey: colgroups[endColIndex].key, startRowKey: allRowKeys[startRowIndex], endRowKey: allRowKeys[endRowIndex], }, data: [], }; const sourceFieldNames = colgroups .slice(startColIndex, endColIndex + 1) .map((x) => x.field); response.data = decodePasteData .slice(0, endRowIndex - startRowIndex + 1) .map((rowData) => { let newRow = {}; rowData.forEach((cellData, cellIndex) => { if (cellIndex <= endColIndex - startColIndex) { newRow[sourceFieldNames[cellIndex]] = cellData; } }); return newRow; }); return response; } /** * @onAfterPaste * @desc on after paste * @param {Event} event * @return */ export function onAfterPaste({ tableData, beforePasteResponse }) { const { data: pasteData, selectionRangeIndexes } = beforePasteResponse; pasteData.forEach((rowData, rowIndex) => { Object.assign( tableData[selectionRangeIndexes.startRowIndex + rowIndex], rowData, ); }); } /** * @onBeforeCut * @desc on before cut * @param {Event} event * @return {selectionRangeIndexes,selectionRangeKeys,data} */ export function onBeforeCut({ cellSelectionRangeData, selectionRangeData, colgroups, allRowKeys, }) { const { leftColKey, rightColKey, topRowKey, bottomRowKey } = cellSelectionRangeData; const selectionRangeIndexes = { startColIndex: colgroups.findIndex((x) => x.key === leftColKey), endColIndex: colgroups.findIndex((x) => x.key === rightColKey), startRowIndex: allRowKeys.indexOf(topRowKey), endRowIndex: allRowKeys.indexOf(bottomRowKey), }; const selectionRangeKeys = { startColKey: leftColKey, endColKey: rightColKey, startRowKey: topRowKey, endRowKey: bottomRowKey, }; const response = { selectionRangeIndexes, selectionRangeKeys, data: selectionRangeData, }; return response; } /** * @onAfterCut * @desc on after cut * @param {Event} event * @return */ export function onAfterCut({ event, tableData, colgroups, selectionRangeData, selectionRangeIndexes, }) { const spreadsheetStr = encodeToSpreadsheetStr(selectionRangeData); const { endColIndex, endRowIndex, startColIndex, startRowIndex } = selectionRangeIndexes; // 移除制定的表格数据 const fieldNames = colgroups .slice(startColIndex, endColIndex + 1) .map((x) => x.field); tableData.forEach((rowData, rowIndex) => { if (rowIndex >= startRowIndex && rowIndex <= endRowIndex) { fieldNames.forEach((fieldName) => { rowData[fieldName] = ""; }); } }); if (event.clipboardData) { event.clipboardData.setData("text/plain", spreadsheetStr); } // IE browser else if (window.clipboardData) { window.clipboardData.setData("Text", spreadsheetStr); } } /** * @onBeforeDelete * @desc on before delete * @param {Event} event * @return {selectionRangeIndexes,selectionRangeKeys,data} */ export function onBeforeDelete({ cellSelectionRangeData, selectionRangeData, colgroups, allRowKeys, }) { const { leftColKey, rightColKey, topRowKey, bottomRowKey } = cellSelectionRangeData; const selectionRangeIndexes = { startColIndex: colgroups.findIndex((x) => x.key === leftColKey), endColIndex: colgroups.findIndex((x) => x.key === rightColKey), startRowIndex: allRowKeys.indexOf(topRowKey), endRowIndex: allRowKeys.indexOf(bottomRowKey), }; const selectionRangeKeys = { startColKey: leftColKey, endColKey: rightColKey, startRowKey: topRowKey, endRowKey: bottomRowKey, }; const response = { selectionRangeIndexes, selectionRangeKeys, data: selectionRangeData, }; return response; } /** * @onAfterDelete * @desc on after delete * @param {Event} event * @return */ export function onAfterDelete({ tableData, colgroups, selectionRangeIndexes }) { const { endColIndex, endRowIndex, startColIndex, startRowIndex } = selectionRangeIndexes; // 移除制定的表格数据 const fieldNames = colgroups .slice(startColIndex, endColIndex + 1) .map((x) => x.field); tableData.forEach((rowData, rowIndex) => { if (rowIndex >= startRowIndex && rowIndex <= endRowIndex) { fieldNames.forEach((fieldName) => { rowData[fieldName] = ""; }); } }); }