@@ -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,7 +35,7 @@ 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 || { } ;
38+ const { copyTypes = [ ] , ...restProps } = options || { } ;
3739 useImperativeHandle ( ref , ( ) => ( {
3840 tableRef,
3941 } ) ) ;
@@ -53,7 +55,7 @@ const SpreadSheet: React.FC<ISpreadSheetProps> = forwardRef(
5355 clearTimeout ( _timer . current ) ;
5456 } ;
5557
56- const getData = ( ) => {
58+ const getShowData = ( ) => {
5759 let showData = data ;
5860 if ( ! showData ?. length ) {
5961 const emptyArr = new Array ( columns . length ) . fill ( '' , 0 , columns . length ) ;
@@ -75,56 +77,102 @@ const SpreadSheet: React.FC<ISpreadSheetProps> = forwardRef(
7577 }
7678 } ;
7779
78- const beforeCopy = ( arr : any [ ] ) => {
79- /**
80- * 去除格式化
81- */
80+ /**
81+ * 去除格式化
82+ */
83+ const beforeCopy = ( arr : Array < Array < any > > ) => {
8284 const value = arr
8385 . map ( ( row : any [ ] ) => {
8486 return row . join ( '\t' ) ;
8587 } )
8688 . join ( '\n' ) ;
89+
8790 copyUtils . copy ( value ) ;
8891 return false ;
8992 } ;
9093
9194 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- } ,
95+ // 获取值
96+ const getCopyData = ( ) => {
97+ // 调用的是 handsontable 的方法(在 handsontable.d.ts), this/that 调用的是当前文件的方法
98+ const selectedIndexArr = tableRef . current ?. hotInstance ?. getSelected ( ) ;
99+ let dataArr : Array < any > = [ ] ;
100+
101+ if ( Array . isArray ( selectedIndexArr ) ) {
102+ selectedIndexArr . forEach ( ( arr , index ) => {
103+ const [ r , c , r2 , c2 ] = arr || [ ] ;
104+ const colData : [ ] =
105+ tableRef . current ?. hotInstance ?. getData ( r , c , r2 , c2 ) || [ ] ;
106+ if ( index === 0 ) {
107+ dataArr . push ( ...colData ) ;
108+ } else {
109+ dataArr = dataArr . map ( ( item : any [ ] , index : number ) => {
110+ return item . concat ( colData [ index ] ) ;
111+ } ) ;
112+ }
113+ } ) ;
114+ }
115+ return dataArr ;
102116 } ;
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 ;
117+ // 获取列名
118+ const getCopyHeaders = ( selection : Array < any > ) => {
119+ // _that 调用的是 handsontable 的方法(在 handsontable.d.ts), this/that 调用的是当前文件的方法
120+ let headerArr : Array < any > = [ ] ;
121+ if ( Array . isArray ( selection ) ) {
122+ selection . forEach ( ( it ) => {
123+ const columnStart = it . start ?. col ;
124+ const columnEnd = it . end ?. col ;
113125 if ( columnStart !== undefined && columnEnd !== undefined ) {
114- columnArr = columns . slice ( columnStart , columnEnd + 1 ) ;
115- }
116- if ( columnArr ) {
117- copyDataArr = [ columnArr , ...copyDataArr ] ;
126+ headerArr = headerArr . concat ( columns . slice ( columnStart , columnEnd + 1 ) ) ;
118127 }
119- beforeCopy ( copyDataArr ) ;
120- } ,
121- } ;
122- // 目前版本不支持 copy_with_column_headers 暂时用 cut 代替,以达到与copy类似的表现
123- items [ 'cut' ] = copyWithHeaderItem ;
128+ } ) ;
129+ }
130+ return headerArr ;
131+ } ;
132+
133+ const copyDataItem = {
134+ name : '复制值' ,
135+ callback : function ( _key : string ) {
136+ const copyDataArr = getCopyData ( ) ;
137+ beforeCopy ( copyDataArr ) ;
138+ } ,
139+ } ;
140+ const copyHeadersItem = {
141+ name : '复制列名' ,
142+ callback : function ( _key : string , selection : Array < any > ) {
143+ const copyHeaders = getCopyHeaders ( selection ) ;
144+ beforeCopy ( [ copyHeaders ] ) ;
145+ } ,
146+ } ;
147+ const copyHeadersAndDataItem = {
148+ name : '复制列名和值' ,
149+ callback : function ( _key : string , selection : Array < any > ) {
150+ const copyDataArr = getCopyData ( ) ;
151+ const copyHeaders = getCopyHeaders ( selection ) ;
152+ beforeCopy ( [ copyHeaders , ...copyDataArr ] ) ;
153+ } ,
154+ } ;
155+
156+ // 目前 items 在 https://github.com/handsontable/handsontable/blob/6.2.2/handsontable.d.ts#L779,自定义方法也可以被执行
157+ const items : Partial < Record < ICopyType , any > > = { } ;
158+ if ( Array . isArray ( copyTypes ) && copyTypes ?. length ) {
159+ // 复制值
160+ if ( copyTypes . includes ( 'copyData' ) ) {
161+ items [ 'copyData' ] = copyDataItem ;
162+ }
163+ // 复制列名
164+ if ( copyTypes . includes ( 'copyHeaders' ) ) {
165+ items [ 'copyHeaders' ] = copyHeadersItem ;
166+ }
167+ // 复制列名和值
168+ if ( copyTypes . includes ( 'copyHeadersAndData' ) ) {
169+ items [ 'copyHeadersAndData' ] = copyHeadersAndDataItem ;
170+ }
171+ } else {
172+ items [ 'copyData' ] = copyDataItem ;
124173 }
125- return {
126- items,
127- } as any ;
174+
175+ return { items } as any ;
128176 } ;
129177
130178 return (
@@ -143,7 +191,7 @@ const SpreadSheet: React.FC<ISpreadSheetProps> = forwardRef(
143191 : columns ?. [ index as number ] ;
144192 return `<span title="${ title } ">${ title } </span>` ;
145193 } }
146- data = { getData ( ) }
194+ data = { getShowData ( ) }
147195 mergeCells = { getMergeCells ( ) }
148196 cell = { getCell ( ) }
149197 readOnly
0 commit comments