@@ -8,9 +8,11 @@ import CopyUtils from '../utils/copy';
88import 'handsontable/dist/handsontable.full.css' ;
99import './style.scss' ;
1010
11+ type ICopyType = 'copyData' | 'copyHeaders' | 'copyHeadersAndData' ;
12+
1113type IOptions = HotTableProps & {
12- /** 是否展示复制值以及列名 */
13- showCopyWithHeader ?: boolean ;
14+ // 右键菜单中展示的选项 复制值/复制列名/复制列名和值 按钮 */
15+ copyTypes ?: ICopyType [ ] ;
1416} ;
1517
1618export interface ISpreadSheetProps {
@@ -33,10 +35,8 @@ const SpreadSheet: React.FC<ISpreadSheetProps> = forwardRef(
3335 const tableRef = useRef < any > ( null ) ;
3436 const copyUtils = new CopyUtils ( ) ;
3537 const _timer = useRef < NodeJS . Timeout > ( ) ;
36- const { showCopyWithHeader, ...restProps } = options || { } ;
37- useImperativeHandle ( ref , ( ) => ( {
38- tableRef,
39- } ) ) ;
38+ const { copyTypes = [ ] , ...restProps } = options || { } ;
39+ useImperativeHandle ( ref , ( ) => tableRef . current ) ;
4040 useEffect ( ( ) => {
4141 if ( tableRef . current ) {
4242 removeRenderClock ( ) ;
@@ -53,7 +53,7 @@ const SpreadSheet: React.FC<ISpreadSheetProps> = forwardRef(
5353 clearTimeout ( _timer . current ) ;
5454 } ;
5555
56- const getData = ( ) => {
56+ const getShowData = ( ) => {
5757 let showData = data ;
5858 if ( ! showData ?. length ) {
5959 const emptyArr = new Array ( columns . length ) . fill ( '' , 0 , columns . length ) ;
@@ -75,56 +75,102 @@ const SpreadSheet: React.FC<ISpreadSheetProps> = forwardRef(
7575 }
7676 } ;
7777
78- const beforeCopy = ( arr : any [ ] ) => {
79- /**
80- * 去除格式化
81- */
78+ /**
79+ * 去除格式化
80+ */
81+ const beforeCopy = ( arr : Array < Array < any > > ) => {
8282 const value = arr
8383 . map ( ( row : any [ ] ) => {
8484 return row . join ( '\t' ) ;
8585 } )
8686 . join ( '\n' ) ;
87+
8788 copyUtils . copy ( value ) ;
8889 return false ;
8990 } ;
9091
9192 const getContextMenu = ( ) => {
92- const items : Record < string , { name : string ; callback : Function } > = {
93- copy : {
94- name : '复制' ,
95- callback : function ( this : any , _key : any ) {
96- const indexArr = this . getSelected ( ) ;
97- // eslint-disable-next-line prefer-spread
98- const copyDataArr = this . getData . apply ( this , indexArr [ 0 ] ) ;
99- beforeCopy ( copyDataArr ) ;
100- } ,
101- } ,
93+ // 获取值
94+ const getCopyData = ( ) => {
95+ // 调用的是 handsontable 的方法(在 handsontable.d.ts), this/that 调用的是当前文件的方法
96+ const selectedIndexArr = tableRef . current ?. hotInstance ?. getSelected ( ) ;
97+ let dataArr : Array < any > = [ ] ;
98+
99+ if ( Array . isArray ( selectedIndexArr ) ) {
100+ selectedIndexArr . forEach ( ( arr , index ) => {
101+ const [ r , c , r2 , c2 ] = arr || [ ] ;
102+ const colData : [ ] =
103+ tableRef . current ?. hotInstance ?. getData ( r , c , r2 , c2 ) || [ ] ;
104+ if ( index === 0 ) {
105+ dataArr . push ( ...colData ) ;
106+ } else {
107+ dataArr = dataArr . map ( ( item : any [ ] , index : number ) => {
108+ return item . concat ( colData [ index ] ) ;
109+ } ) ;
110+ }
111+ } ) ;
112+ }
113+ return dataArr ;
102114 } ;
103- if ( showCopyWithHeader ) {
104- const copyWithHeaderItem = {
105- name : '复制值以及列名' ,
106- callback : function ( this : any , _key : any , selection : any ) {
107- const indexArr = this . getSelected ( ) ;
108- // eslint-disable-next-line prefer-spread
109- let copyDataArr = this . getData . apply ( this , indexArr [ 0 ] ) ;
110- const columnStart = selection ?. [ 0 ] ?. start ?. col ;
111- const columnEnd = selection ?. [ 0 ] ?. end ?. col ;
112- let columnArr ;
115+ // 获取列名
116+ const getCopyHeaders = ( selection : Array < any > ) => {
117+ // _that 调用的是 handsontable 的方法(在 handsontable.d.ts), this/that 调用的是当前文件的方法
118+ let headerArr : Array < any > = [ ] ;
119+ if ( Array . isArray ( selection ) ) {
120+ selection . forEach ( ( it ) => {
121+ const columnStart = it . start ?. col ;
122+ const columnEnd = it . end ?. col ;
113123 if ( columnStart !== undefined && columnEnd !== undefined ) {
114- columnArr = columns . slice ( columnStart , columnEnd + 1 ) ;
115- }
116- if ( columnArr ) {
117- copyDataArr = [ columnArr , ...copyDataArr ] ;
124+ headerArr = headerArr . concat ( columns . slice ( columnStart , columnEnd + 1 ) ) ;
118125 }
119- beforeCopy ( copyDataArr ) ;
120- } ,
121- } ;
122- // 目前版本不支持 copy_with_column_headers 暂时用 cut 代替,以达到与copy类似的表现
123- items [ 'cut' ] = copyWithHeaderItem ;
126+ } ) ;
127+ }
128+ return headerArr ;
129+ } ;
130+
131+ const copyDataItem = {
132+ name : '复制值' ,
133+ callback : function ( _key : string ) {
134+ const copyDataArr = getCopyData ( ) ;
135+ beforeCopy ( copyDataArr ) ;
136+ } ,
137+ } ;
138+ const copyHeadersItem = {
139+ name : '复制列名' ,
140+ callback : function ( _key : string , selection : Array < any > ) {
141+ const copyHeaders = getCopyHeaders ( selection ) ;
142+ beforeCopy ( [ copyHeaders ] ) ;
143+ } ,
144+ } ;
145+ const copyHeadersAndDataItem = {
146+ name : '复制列名和值' ,
147+ callback : function ( _key : string , selection : Array < any > ) {
148+ const copyDataArr = getCopyData ( ) ;
149+ const copyHeaders = getCopyHeaders ( selection ) ;
150+ beforeCopy ( [ copyHeaders , ...copyDataArr ] ) ;
151+ } ,
152+ } ;
153+
154+ // 目前 items 在 https://github.com/handsontable/handsontable/blob/6.2.2/handsontable.d.ts#L779,自定义方法也可以被执行
155+ const items : Partial < Record < ICopyType , any > > = { } ;
156+ if ( Array . isArray ( copyTypes ) && copyTypes ?. length ) {
157+ // 复制值
158+ if ( copyTypes . includes ( 'copyData' ) ) {
159+ items [ 'copyData' ] = copyDataItem ;
160+ }
161+ // 复制列名
162+ if ( copyTypes . includes ( 'copyHeaders' ) ) {
163+ items [ 'copyHeaders' ] = copyHeadersItem ;
164+ }
165+ // 复制列名和值
166+ if ( copyTypes . includes ( 'copyHeadersAndData' ) ) {
167+ items [ 'copyHeadersAndData' ] = copyHeadersAndDataItem ;
168+ }
169+ } else {
170+ items [ 'copyData' ] = copyDataItem ;
124171 }
125- return {
126- items,
127- } as any ;
172+
173+ return { items } as any ;
128174 } ;
129175
130176 return (
@@ -143,7 +189,7 @@ const SpreadSheet: React.FC<ISpreadSheetProps> = forwardRef(
143189 : columns ?. [ index as number ] ;
144190 return `<span title="${ title } ">${ title } </span>` ;
145191 } }
146- data = { getData ( ) }
192+ data = { getShowData ( ) }
147193 mergeCells = { getMergeCells ( ) }
148194 cell = { getCell ( ) }
149195 readOnly
0 commit comments