70 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			70 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | /* sheetjs (C) SheetJS -- https://sheetjs.com */ | |||
|  | 
 | |||
|  | import './App.css' | |||
|  | import { useCallback, useState } from '@lynx-js/react' | |||
|  | import SheetJSLogo from './assets/SheetJS-logo.png'; | |||
|  | import { read, utils, WorkSheet } from 'xlsx'; | |||
|  | 
 | |||
|  | const make_width = (ws: WorkSheet): number[] => { | |||
|  |     const aoa = utils.sheet_to_json(ws, { header: 1 }), res: number[] = []; | |||
|  |     aoa.forEach((r: any) => { r.forEach((c: any, C: any) => { res[C] = Math.max(res[C] || 60, String(c).length * 10); }); }); | |||
|  |     for (let C = 0; C < res.length; ++C) if (!res[C]) res[C] = 60; | |||
|  |     return res; | |||
|  | }; | |||
|  | 
 | |||
|  | export function App() { | |||
|  |     const [data, setData] = useState<any[]>([ | |||
|  |         "SheetJS".split(""), | |||
|  |         [5, 4, 3, 3, 7, 9, 5], | |||
|  |         [8, 6, 7, 5, 3, 0, 9] | |||
|  |     ]); | |||
|  |     const [widths, setWidths] = useState<number[]>(Array.from({ length: 7 }, () => 20)); | |||
|  | 
 | |||
|  |     const importFile = useCallback(async () => { | |||
|  |         try { | |||
|  |             const ab = await (await fetch("https://docs.sheetjs.com/pres.numbers")).arrayBuffer(); | |||
|  |             const wb = read(ab); | |||
|  | 
 | |||
|  |             /* convert first worksheet to AOA */ | |||
|  |             const wsname = wb.SheetNames[0]; | |||
|  |             const ws = wb.Sheets[wsname]; | |||
|  |             const data = utils.sheet_to_json(ws, { header: 1 }); | |||
|  |             /* update state */ | |||
|  |             setData(data); | |||
|  |             console.log(data); | |||
|  | 
 | |||
|  |             setWidths(make_width(ws)); | |||
|  |         } catch (err) { | |||
|  |             console.log("importFile Error", "Error " + ((err as any).message || err)); | |||
|  |         } | |||
|  |     }, []); | |||
|  | 
 | |||
|  |     return ( | |||
|  |         <view className='App'> | |||
|  |             <text className="Title"> | |||
|  |                 <image className="Logo" src={SheetJSLogo} />   SheetJS × React Lynx | |||
|  |             </text> | |||
|  |             <view className="Button" bindtap={importFile}> | |||
|  |                 <text>IMPORT DATA FROM A SPREADSHEET</text> | |||
|  |             </view> | |||
|  |             <text style={{ margin: '8px', fontWeight: '600'}}>Current Data</text> | |||
|  |             <view className='Table'> | |||
|  |                 {data.map((row, rowIndex) => ( | |||
|  |                     <view key={`row-${rowIndex}`} className="Row"> | |||
|  |                         {Array.isArray(row) && row.map((cell, cellIndex) => ( | |||
|  |                             <view | |||
|  |                                 key={`cell-${rowIndex}-${cellIndex}`} | |||
|  |                                 className="Cell" | |||
|  |                                 style={{ width: `${widths[cellIndex]}px` }} | |||
|  |                             > | |||
|  |                                 <text>{cell}</text> | |||
|  |                             </view> | |||
|  |                         ))} | |||
|  |                     </view> | |||
|  |                 ))} | |||
|  |             </view> | |||
|  |             <view style={{ flex: 1 }}></view> | |||
|  |         </view> | |||
|  |     ) | |||
|  | } |