@@ -30,8 +30,10 @@ const (
30
30
CellTypeBool
31
31
CellTypeDate
32
32
CellTypeError
33
+ CellTypeFormula
34
+ CellTypeInlineString
33
35
CellTypeNumber
34
- CellTypeString
36
+ CellTypeSharedString
35
37
)
36
38
37
39
const (
@@ -51,9 +53,9 @@ var cellTypes = map[string]CellType{
51
53
"d" : CellTypeDate ,
52
54
"n" : CellTypeNumber ,
53
55
"e" : CellTypeError ,
54
- "s" : CellTypeString ,
55
- "str" : CellTypeString ,
56
- "inlineStr" : CellTypeString ,
56
+ "s" : CellTypeSharedString ,
57
+ "str" : CellTypeFormula ,
58
+ "inlineStr" : CellTypeInlineString ,
57
59
}
58
60
59
61
// GetCellValue provides a function to get formatted value from cell by given
@@ -235,8 +237,7 @@ func (f *File) setCellTimeFunc(sheet, cell string, value time.Time) error {
235
237
date1904 = wb .WorkbookPr .Date1904
236
238
}
237
239
var isNum bool
238
- c .T , c .V , isNum , err = setCellTime (value , date1904 )
239
- if err != nil {
240
+ if isNum , err = c .setCellTime (value , date1904 ); err != nil {
240
241
return err
241
242
}
242
243
if isNum {
@@ -247,7 +248,7 @@ func (f *File) setCellTimeFunc(sheet, cell string, value time.Time) error {
247
248
248
249
// setCellTime prepares cell type and Excel time by given Go time.Time type
249
250
// timestamp.
250
- func setCellTime (value time.Time , date1904 bool ) (t string , b string , isNum bool , err error ) {
251
+ func ( c * xlsxC ) setCellTime (value time.Time , date1904 bool ) (isNum bool , err error ) {
251
252
var excelTime float64
252
253
_ , offset := value .In (value .Location ()).Zone ()
253
254
value = value .Add (time .Duration (offset ) * time .Second )
@@ -256,9 +257,9 @@ func setCellTime(value time.Time, date1904 bool) (t string, b string, isNum bool
256
257
}
257
258
isNum = excelTime > 0
258
259
if isNum {
259
- t , b = setCellDefault (strconv .FormatFloat (excelTime , 'f' , - 1 , 64 ))
260
+ c . setCellDefault (strconv .FormatFloat (excelTime , 'f' , - 1 , 64 ))
260
261
} else {
261
- t , b = setCellDefault (value .Format (time .RFC3339Nano ))
262
+ c . setCellDefault (value .Format (time .RFC3339Nano ))
262
263
}
263
264
return
264
265
}
@@ -435,14 +436,14 @@ func (f *File) setSharedString(val string) (int, error) {
435
436
sst .Count ++
436
437
sst .UniqueCount ++
437
438
t := xlsxT {Val : val }
438
- _ , val , t .Space = setCellStr (val )
439
+ val , t .Space = trimCellValue (val )
439
440
sst .SI = append (sst .SI , xlsxSI {T : & t })
440
441
f .sharedStringsMap [val ] = sst .UniqueCount - 1
441
442
return sst .UniqueCount - 1 , nil
442
443
}
443
444
444
- // setCellStr provides a function to set string type to cell.
445
- func setCellStr (value string ) (t string , v string , ns xml.Attr ) {
445
+ // trimCellValue provides a function to set string type to cell.
446
+ func trimCellValue (value string ) (v string , ns xml.Attr ) {
446
447
if len (value ) > TotalCellChars {
447
448
value = value [:TotalCellChars ]
448
449
}
@@ -458,10 +459,117 @@ func setCellStr(value string) (t string, v string, ns xml.Attr) {
458
459
}
459
460
}
460
461
}
461
- t , v = "str" , bstrMarshal (value )
462
+ v = bstrMarshal (value )
462
463
return
463
464
}
464
465
466
+ // setCellValue set cell data type and value for (inline) rich string cell or
467
+ // formula cell.
468
+ func (c * xlsxC ) setCellValue (val string ) {
469
+ if c .F != nil {
470
+ c .setStr (val )
471
+ return
472
+ }
473
+ c .setInlineStr (val )
474
+ }
475
+
476
+ // setInlineStr set cell data type and value which containing an (inline) rich
477
+ // string.
478
+ func (c * xlsxC ) setInlineStr (val string ) {
479
+ c .T , c .V , c .IS = "inlineStr" , "" , & xlsxSI {T : & xlsxT {}}
480
+ c .IS .T .Val , c .IS .T .Space = trimCellValue (val )
481
+ }
482
+
483
+ // setStr set cell data type and value which containing a formula string.
484
+ func (c * xlsxC ) setStr (val string ) {
485
+ c .T , c .IS = "str" , nil
486
+ c .V , c .XMLSpace = trimCellValue (val )
487
+ }
488
+
489
+ // getCellDate parse cell value which containing a boolean.
490
+ func (c * xlsxC ) getCellBool (f * File , raw bool ) (string , error ) {
491
+ if ! raw {
492
+ if c .V == "1" {
493
+ return "TRUE" , nil
494
+ }
495
+ if c .V == "0" {
496
+ return "FALSE" , nil
497
+ }
498
+ }
499
+ return f .formattedValue (c .S , c .V , raw ), nil
500
+ }
501
+
502
+ // setCellDefault prepares cell type and string type cell value by a given
503
+ // string.
504
+ func (c * xlsxC ) setCellDefault (value string ) {
505
+ if ok , _ , _ := isNumeric (value ); ! ok {
506
+ c .setInlineStr (value )
507
+ c .IS .T .Val = value
508
+ return
509
+ }
510
+ c .V = value
511
+ }
512
+
513
+ // getCellDate parse cell value which contains a date in the ISO 8601 format.
514
+ func (c * xlsxC ) getCellDate (f * File , raw bool ) (string , error ) {
515
+ if ! raw {
516
+ layout := "20060102T150405.999"
517
+ if strings .HasSuffix (c .V , "Z" ) {
518
+ layout = "20060102T150405Z"
519
+ if strings .Contains (c .V , "-" ) {
520
+ layout = "2006-01-02T15:04:05Z"
521
+ }
522
+ } else if strings .Contains (c .V , "-" ) {
523
+ layout = "2006-01-02 15:04:05Z"
524
+ }
525
+ if timestamp , err := time .Parse (layout , strings .ReplaceAll (c .V , "," , "." )); err == nil {
526
+ excelTime , _ := timeToExcelTime (timestamp , false )
527
+ c .V = strconv .FormatFloat (excelTime , 'G' , 15 , 64 )
528
+ }
529
+ }
530
+ return f .formattedValue (c .S , c .V , raw ), nil
531
+ }
532
+
533
+ // getValueFrom return a value from a column/row cell, this function is
534
+ // intended to be used with for range on rows an argument with the spreadsheet
535
+ // opened file.
536
+ func (c * xlsxC ) getValueFrom (f * File , d * xlsxSST , raw bool ) (string , error ) {
537
+ f .Lock ()
538
+ defer f .Unlock ()
539
+ switch c .T {
540
+ case "b" :
541
+ return c .getCellBool (f , raw )
542
+ case "d" :
543
+ return c .getCellDate (f , raw )
544
+ case "s" :
545
+ if c .V != "" {
546
+ xlsxSI := 0
547
+ xlsxSI , _ = strconv .Atoi (c .V )
548
+ if _ , ok := f .tempFiles .Load (defaultXMLPathSharedStrings ); ok {
549
+ return f .formattedValue (c .S , f .getFromStringItem (xlsxSI ), raw ), nil
550
+ }
551
+ if len (d .SI ) > xlsxSI {
552
+ return f .formattedValue (c .S , d .SI [xlsxSI ].String (), raw ), nil
553
+ }
554
+ }
555
+ return f .formattedValue (c .S , c .V , raw ), nil
556
+ case "inlineStr" :
557
+ if c .IS != nil {
558
+ return f .formattedValue (c .S , c .IS .String (), raw ), nil
559
+ }
560
+ return f .formattedValue (c .S , c .V , raw ), nil
561
+ default :
562
+ if isNum , precision , decimal := isNumeric (c .V ); isNum && ! raw {
563
+ if precision > 15 {
564
+ c .V = strconv .FormatFloat (decimal , 'G' , 15 , 64 )
565
+ } else {
566
+ c .V = strconv .FormatFloat (decimal , 'f' , - 1 , 64 )
567
+ }
568
+ }
569
+ return f .formattedValue (c .S , c .V , raw ), nil
570
+ }
571
+ }
572
+
465
573
// SetCellDefault provides a function to set string type value of a cell as
466
574
// default format without escaping the cell.
467
575
func (f * File ) SetCellDefault (sheet , cell , value string ) error {
@@ -476,22 +584,11 @@ func (f *File) SetCellDefault(sheet, cell, value string) error {
476
584
ws .Lock ()
477
585
defer ws .Unlock ()
478
586
c .S = f .prepareCellStyle (ws , col , row , c .S )
479
- c .T , c .V = setCellDefault (value )
480
- c .IS = nil
587
+ c .setCellDefault (value )
481
588
f .removeFormula (c , ws , sheet )
482
589
return err
483
590
}
484
591
485
- // setCellDefault prepares cell type and string type cell value by a given
486
- // string.
487
- func setCellDefault (value string ) (t string , v string ) {
488
- if ok , _ , _ := isNumeric (value ); ! ok {
489
- t = "str"
490
- }
491
- v = value
492
- return
493
- }
494
-
495
592
// GetCellFormula provides a function to get formula from cell by given
496
593
// worksheet name and cell reference in spreadsheet.
497
594
func (f * File ) GetCellFormula (sheet , cell string ) (string , error ) {
@@ -625,7 +722,7 @@ func (f *File) SetCellFormula(sheet, cell, formula string, opts ...FormulaOpts)
625
722
c .F .Ref = * opt .Ref
626
723
}
627
724
}
628
- c .IS = nil
725
+ c .T , c . IS = "str" , nil
629
726
return err
630
727
}
631
728
@@ -900,7 +997,7 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
900
997
return textRuns , ErrCellCharsLength
901
998
}
902
999
run := xlsxR {T : & xlsxT {}}
903
- _ , run .T .Val , run .T .Space = setCellStr (textRun .Text )
1000
+ run .T .Val , run .T .Space = trimCellValue (textRun .Text )
904
1001
fnt := textRun .Font
905
1002
if fnt != nil {
906
1003
run .RPr = newRpr (fnt )
0 commit comments