@@ -16,7 +16,6 @@ import {
16
16
ProgressBar ,
17
17
shorthands
18
18
} from "@fluentui/react-components" ;
19
- import { getCellAddress } from "../taskpane" ;
20
19
import { useState } from "react" ;
21
20
import pako from 'pako' ;
22
21
@@ -135,6 +134,15 @@ const useStyles = makeStyles({
135
134
}
136
135
} ) ;
137
136
137
+ // Helper to convert Excel column letters to zero-based index
138
+ function columnLetterToIndex ( colLetters : string ) {
139
+ let col = 0 ;
140
+ for ( let i = 0 ; i < colLetters . length ; i ++ ) {
141
+ col = col * 26 + ( colLetters . charCodeAt ( i ) - 64 ) ; // 'A' is 65 in ASCII
142
+ }
143
+ return col - 1 ; // zero-based
144
+ }
145
+
138
146
const App = ( ) => {
139
147
const styles = useStyles ( ) ;
140
148
const [ selectedTab , setSelectedTab ] = useState ( "read" ) ;
@@ -205,11 +213,20 @@ const App = () => {
205
213
206
214
for ( let row = 0 ; row < range . rowCount ; row ++ ) {
207
215
for ( let col = 0 ; col < range . columnCount ; col ++ ) {
216
+ const address = properties . value [ row ] [ col ] . address ;
217
+ const match = address . match ( / ! ( [ A - Z ] + ) ( \d + ) $ / ) ;
218
+ let rowIndex = 0 , columnIndex = 0 ; // fallback if parsing fails
219
+ if ( match ) {
220
+ const colLetters = match [ 1 ] ;
221
+ const rowNumber = parseInt ( match [ 2 ] , 10 ) ;
222
+ rowIndex = rowNumber - 1 ; // zero-based
223
+ columnIndex = columnLetterToIndex ( colLetters ) ;
224
+ }
208
225
const cellData = {
209
226
formulaR1C1 : range . formulasR1C1 [ row ] [ col ] ,
210
- address : properties . value [ row ] [ col ] . address ,
211
- rowIndex : row ,
212
- columnIndex : col ,
227
+ address : address ,
228
+ rowIndex : rowIndex ,
229
+ columnIndex : columnIndex ,
213
230
format : {
214
231
font : {
215
232
bold : properties . value [ row ] [ col ] . format . font . bold ,
@@ -358,11 +375,150 @@ const App = () => {
358
375
}
359
376
} ;
360
377
378
+ // const convertTo2DArray = async function (cellDict) {
379
+ // // Helper function to parse row and column from address (e.g., "Summary!A3" -> row 3, col A)
380
+ // function parseAddress(address) {
381
+ // const match = address.match(/!([A-Z]+)(\d+)/);
382
+ // if (!match) return { row: 0, col: 0 };
383
+ // const colLetter = match[1];
384
+ // const row = parseInt(match[2], 10) - 1; // Convert to 0-based index
385
+ // // Convert column letter to 0-based index (A=0, B=1, etc.)
386
+ // let col = 0;
387
+ // for (let i = 0; i < colLetter.length; i++) {
388
+ // col = col * 26 + (colLetter.charCodeAt(i) - 65 + 1);
389
+ // }
390
+ // return { row, col: col - 1 }; // Adjust to 0-based
391
+ // }
392
+
393
+ // // Find maximum row and column indices
394
+ // let maxRow = 0;
395
+ // let maxCol = 0;
396
+ // for (const cell of Object.values(cellDict)) {
397
+ // const { row, col } = parseAddress(cell.address);
398
+ // maxRow = Math.max(maxRow, row);
399
+ // maxCol = Math.max(maxCol, col);
400
+ // }
401
+
402
+ // // Initialize three 2D arrays
403
+ // const properties = Array(maxRow + 1).fill().map(() => Array(maxCol + 1).fill(undefined));
404
+ // const formulas = Array(maxRow + 1).fill().map(() => Array(maxCol + 1).fill(undefined));
405
+ // const numberFormats = Array(maxRow + 1).fill().map(() => Array(maxCol + 1).fill(undefined));
406
+
407
+ // // Populate the arrays
408
+ // for (const cell of Object.values(cellDict)) {
409
+ // const { row, col } = parseAddress(cell.address);
410
+ // // Properties array
411
+ // properties[row][col] = {
412
+ // format: {
413
+ // fill: {
414
+ // color: cell.format.backgroundColor
415
+ // },
416
+ // font: {
417
+ // bold: cell.format.font.bold,
418
+ // color: cell.format.font.color,
419
+ // italic: cell.format.font.italic,
420
+ // name: cell.format.font.name,
421
+ // size: cell.format.font.size,
422
+ // strikethrough: cell.format.font.strikethrough || false, // Default to false if undefined
423
+ // underline: cell.format.font.underline
424
+ // }
425
+ // }
426
+ // };
427
+ // // Formulas array
428
+ // formulas[row][col] = cell.formulaR1C1;
429
+ // // Number formats array
430
+ // numberFormats[row][col] = cell.format.numberFormat;
431
+ // }
432
+
433
+ // return { properties, formulas, numberFormats };
434
+ // }
435
+
436
+ function parseExcelJsonTo2DArrays ( jsonData ) {
437
+ // Find the maximum row and column indices
438
+ let maxRow = 0 ;
439
+ let maxCol = 0 ;
440
+
441
+ Object . values ( jsonData ) . forEach ( ( cell : any ) => {
442
+ maxRow = Math . max ( maxRow , cell . rowIndex ) ;
443
+ maxCol = Math . max ( maxCol , cell . columnIndex ) ;
444
+ } ) ;
445
+
446
+ // Initialize 2D arrays with appropriate dimensions
447
+ const properties : Excel . SettableCellProperties [ ] [ ] = [ ] ;
448
+ const formulas = [ ] ;
449
+ const numberFormats = [ ] ;
450
+
451
+ // Initialize arrays with empty values
452
+ for ( let row = 0 ; row <= maxRow ; row ++ ) {
453
+ properties [ row ] = [ ] ;
454
+ formulas [ row ] = [ ] ;
455
+ numberFormats [ row ] = [ ] ;
456
+
457
+ for ( let col = 0 ; col <= maxCol ; col ++ ) {
458
+ // Default values for empty cells - RangeUpdateData format
459
+ properties [ row ] [ col ] = {
460
+ format : {
461
+ fill : {
462
+ color : "#FFFFFF"
463
+ } ,
464
+ font : {
465
+ bold : false ,
466
+ color : "#000000" ,
467
+ italic : false ,
468
+ name : "Calibri" ,
469
+ size : 11 ,
470
+ strikethrough : false ,
471
+ underline : Excel . RangeUnderlineStyle . none
472
+ }
473
+ }
474
+ } ;
475
+ formulas [ row ] [ col ] = "" ;
476
+ numberFormats [ row ] [ col ] = "General" ;
477
+ }
478
+ }
479
+
480
+ // Populate arrays with actual data
481
+ Object . values ( jsonData ) . forEach ( ( cell : any ) => {
482
+ const { rowIndex, columnIndex } = cell ;
483
+
484
+ // Properties array - RangeUpdateData format
485
+ properties [ rowIndex ] [ columnIndex ] = {
486
+ format : {
487
+ fill : {
488
+ color : cell . format . backgroundColor
489
+ } ,
490
+ font : {
491
+ bold : cell . format . font . bold ,
492
+ color : cell . format . font . color ,
493
+ italic : cell . format . font . italic ,
494
+ name : cell . format . font . name ,
495
+ size : cell . format . font . size ,
496
+ strikethrough : cell . format . font . strikethrough || false ,
497
+ underline : cell . format . font . underline . toLowerCase ( ) === "none"
498
+ ? Excel . RangeUnderlineStyle . none
499
+ : Excel . RangeUnderlineStyle . single
500
+ }
501
+ }
502
+ } ;
503
+
504
+ // Formulas array
505
+ formulas [ rowIndex ] [ columnIndex ] = cell . formulaR1C1 ;
506
+
507
+ // Number formats array
508
+ numberFormats [ rowIndex ] [ columnIndex ] = cell . format . numberFormat ;
509
+ } ) ;
510
+
511
+ return {
512
+ properties,
513
+ formulas,
514
+ numberFormats
515
+ } ;
516
+ }
517
+
361
518
const writeWorkbook = async ( jsonData : any ) => {
362
519
await Excel . run ( async ( context ) => {
363
520
try {
364
- const workbook = context . workbook ;
365
- const worksheets = workbook . worksheets ;
521
+ const worksheets = context . workbook . worksheets ;
366
522
367
523
// Loop through each worksheet in the JSON data
368
524
for ( const sheetData of jsonData . worksheets ) {
@@ -372,53 +528,20 @@ const App = () => {
372
528
// If the worksheet does not exist, create it
373
529
if ( worksheet . isNullObject ) {
374
530
worksheet = worksheets . add ( sheetData . name ) ;
531
+ worksheet . activate ( ) ;
375
532
}
376
533
377
- // Loop through each cell in the worksheet
378
- for ( const cellAddress in sheetData . cells ) {
379
- const cellData = sheetData . cells [ cellAddress ] ;
380
- const range = worksheet . getRange ( cellAddress ) ;
381
-
382
- // Set cell value
383
- if ( cellData . value !== undefined ) {
384
- range . values = [ [ cellData . value ] ] ;
385
- }
386
-
387
- // Set cell formula
388
- if ( cellData . formula !== undefined ) {
389
- range . formulas = [ [ cellData . formula ] ] ;
390
- }
391
-
392
- // Set cell formulaR1C1
393
- if ( cellData . formulaR1C1 !== undefined ) {
394
- range . formulasR1C1 = [ [ cellData . formulaR1C1 ] ] ;
395
- }
396
-
397
- // Set cell format
398
- if ( cellData . format ) {
399
- const format = cellData . format ;
400
-
401
- if ( format . font ) {
402
- range . format . font . name = format . font . name ;
403
- range . format . font . size = format . font . size ;
404
- range . format . font . bold = format . font . bold ;
405
- range . format . font . italic = format . font . italic ;
406
- range . format . font . underline = format . font . underline ;
407
- range . format . font . strikethrough = format . font . strikethrough ;
408
- range . format . font . color = format . font . color ;
409
- }
410
-
411
- if ( format . backgroundColor ) {
412
- range . format . fill . color = format . backgroundColor ;
413
- }
534
+ let sheet_cells = worksheet . getRange ( sheetData . cells [ Object . keys ( sheetData . cells ) [ 0 ] ] . address + ":" + sheetData . cells [ Object . keys ( sheetData . cells ) [ Object . keys ( sheetData . cells ) . length - 1 ] ] . address ) ;
535
+ const { properties, formulas, numberFormats } = parseExcelJsonTo2DArrays ( sheetData . cells ) ;
536
+ sheet_cells . set ( {
537
+ formulasR1C1 : formulas ,
538
+ numberFormat : numberFormats
539
+ } ) ;
540
+ sheet_cells . setCellProperties ( properties ) ;
541
+ sheet_cells . untrack ( ) ;
414
542
415
- if ( format . numberFormat ) {
416
- range . numberFormat = [ [ format . numberFormat ] ] ;
417
- }
418
- }
419
- }
543
+ await context . sync ( ) ;
420
544
}
421
- await context . sync ( ) ;
422
545
} catch ( error ) {
423
546
setWriteErrorMessage ( error . message ) ;
424
547
throw error ;
0 commit comments