From 1e372f17256733438c67123cb88e590fcaf1e128 Mon Sep 17 00:00:00 2001 From: "owen.wjh" Date: Mon, 3 Apr 2023 16:20:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E4=BB=8Eexcel?= =?UTF-8?q?=E7=B2=98=E8=B4=B4=E5=80=BC=E8=BF=9B=E7=BC=96=E8=BE=91=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sheets/editable-sheet/index.tsx | 2 + .../sheets/editable-sheet/paste.tsx | 81 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 packages/s2-react/src/components/sheets/editable-sheet/paste.tsx diff --git a/packages/s2-react/src/components/sheets/editable-sheet/index.tsx b/packages/s2-react/src/components/sheets/editable-sheet/index.tsx index 16995efbcb..18343571a5 100644 --- a/packages/s2-react/src/components/sheets/editable-sheet/index.tsx +++ b/packages/s2-react/src/components/sheets/editable-sheet/index.tsx @@ -3,6 +3,7 @@ import { BaseSheet } from '../base-sheet'; import type { SheetComponentsProps } from '../interface'; import { EditCell } from './edit-cell'; import { DragCopyPoint } from './drag-copy'; +import { PastePlugin } from './paste'; export const EditableSheet: React.FC = React.memo( (props) => { @@ -10,6 +11,7 @@ export const EditableSheet: React.FC = React.memo( {}} /> + ); }, diff --git a/packages/s2-react/src/components/sheets/editable-sheet/paste.tsx b/packages/s2-react/src/components/sheets/editable-sheet/paste.tsx new file mode 100644 index 0000000000..b89363f2ae --- /dev/null +++ b/packages/s2-react/src/components/sheets/editable-sheet/paste.tsx @@ -0,0 +1,81 @@ +import { useEffect } from 'react'; +import { CellTypes, SpreadSheet } from '@antv/s2'; +import { useSpreadSheetRef } from '../../../utils/SpreadSheetContext'; + +const getDisplayRowMappedIndex = ( + rowIndex: number, + spreadsheet: SpreadSheet, +) => { + const data = spreadsheet.dataSet.getDisplayDataSet()[rowIndex]; + return spreadsheet.dataSet.originData.findIndex((val) => val === data); +}; + +/** + * 粘贴值功能 + * @returns + */ +export const PastePlugin = () => { + const spreadsheet = useSpreadSheetRef(); + + useEffect(() => { + const handlePaste = async () => { + try { + // 批量黏贴数据 + const meta = spreadsheet.interaction + .getInteractedCells() + .filter((cell) => cell.cellType === CellTypes.DATA_CELL)[0] + .getMeta(); + + const activeDom = document.activeElement; + if (meta && activeDom?.tagName === 'BODY') { + const { rowIndex, colIndex } = meta; + const source = spreadsheet.dataSet.originData; + const clipboardItems = await navigator.clipboard.read(); + const result = await clipboardItems[0]?.getType('text/html'); + const tableNode = await result.text(); + const $doc = new DOMParser().parseFromString(tableNode, 'text/html'); + const $trs = Array.from($doc.querySelectorAll('table tr')); + const lines = $trs.map((tr) => + Array.from(tr.children).map((td) => td.textContent || ''), + ); + const columns = spreadsheet.dataCfg.fields.columns; + + lines.forEach((line, idx) => { + const originIndex = getDisplayRowMappedIndex( + rowIndex + idx, + spreadsheet, + ); + // 当列不存在时,代表需要新增列 + if (originIndex === -1) { + const addedRow = {}; + columns.slice(colIndex, line.length).forEach((col, indx) => { + addedRow[col as string] = line[indx]; + }); + spreadsheet.dataSet.originData.push(addedRow); + } else { + line.forEach((val, colIdx) => { + const sanitizedVal = (val || '').replace(/^"|"$/g, ''); + const originalColIdx = colIndex + colIdx; + + if (columns[originalColIdx]) { + source[originIndex][columns[originalColIdx] as string] = + sanitizedVal; + } + }); + } + }); + + spreadsheet.render(); + } + } catch (error) { + // console.info(error); + } + }; + window.addEventListener('paste', handlePaste); + return () => { + window.removeEventListener('paste', handlePaste); + }; + }, [spreadsheet]); + + return null; +};