ooxml

Check-in [266ee51947]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:merged from trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tcltest
Files: files | file ages | folders
SHA3-256: 266ee51947f6a638ded2ab5715ba81fa783e1beab0b7b6472e0954c0f1e44c01
User & Date: alex 2019-11-22 14:15:05
Context
2019-11-26
16:16
adding new tests to formatcell.test; border and style are not ready yet check-in: 9ecd5219d6 user: alex tags: tcltest
2019-11-22
14:16
merged from tcltest check-in: 0445908180 user: alex tags: trunk
14:15
merged from trunk check-in: 266ee51947 user: alex tags: tcltest
13:12
small fix to all samples check-in: 88bbab26e4 user: alex tags: trunk
2019-11-20
20:30
save internal data for analysis check-in: cb48de9043 user: alex tags: tcltest
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to examples/original_excel.xlsx.

cannot compute difference between binary files

Changes to examples/sample1.tcl.

34
35
36
37
38
39
40
41
42
43
44
	$spreadsheet cell $sheet $value -index $name -string
      }
      default {
	$spreadsheet cell $sheet $value -index $name -globalstyle
      }
    }
  }

  $spreadsheet write export1.xlsx
}
$spreadsheet destroy







|
|
<

34
35
36
37
38
39
40
41
42

43
	$spreadsheet cell $sheet $value -index $name -string
      }
      default {
	$spreadsheet cell $sheet $value -index $name -globalstyle
      }
    }
  }
}
$spreadsheet write export1.xlsx

$spreadsheet destroy

Changes to examples/sample2.tcl.

35
36
37
38
39
40
41
42
43
44

	$spreadsheet cell $sheet $data($name) -index $col -string
      }
      default {
	$spreadsheet cell $sheet $data($name) -index $col -globalstyle
      }
    }
  }

  $spreadsheet write export2.xlsx
}








|
|
<
>
35
36
37
38
39
40
41
42
43

44
	$spreadsheet cell $sheet $data($name) -index $col -string
      }
      default {
	$spreadsheet cell $sheet $data($name) -index $col -globalstyle
      }
    }
  }
}
$spreadsheet write export2.xlsx

$spreadsheet destroy

Changes to examples/sample4.tcl.

11
12
13
14
15
16
17
18
19
20
21

set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}]
if {[set sheet [$spreadsheet worksheet {Tabelle 1}]] > -1} {
  $spreadsheet row $sheet
  $spreadsheet cell $sheet 3
  $spreadsheet cell $sheet 5
  $spreadsheet cell $sheet {} -formula A1+B1

  $spreadsheet write export4.xlsx
}
$spreadsheet destroy







|
|
<

11
12
13
14
15
16
17
18
19

20

set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}]
if {[set sheet [$spreadsheet worksheet {Tabelle 1}]] > -1} {
  $spreadsheet row $sheet
  $spreadsheet cell $sheet 3
  $spreadsheet cell $sheet 5
  $spreadsheet cell $sheet {} -formula A1+B1
}
$spreadsheet write export4.xlsx

$spreadsheet destroy

Changes to examples/sample5.tcl.

9
10
11
12
13
14
15
16
17

18

set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}]
if {[set sheet [$spreadsheet worksheet {Tabelle 1}]] > -1} {
  set date [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]]
  $spreadsheet defaultdatestyle $date
  # 2018-03-02 17:39 -> 43161.73542
  $spreadsheet cell $sheet "2018-03-02 17:39" -index 0,0
  $spreadsheet write export5.xlsx
}

$spreadsheet destroy







<

>

9
10
11
12
13
14
15

16
17
18

set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}]
if {[set sheet [$spreadsheet worksheet {Tabelle 1}]] > -1} {
  set date [$spreadsheet style -numfmt [$spreadsheet numberformat -datetime]]
  $spreadsheet defaultdatestyle $date
  # 2018-03-02 17:39 -> 43161.73542
  $spreadsheet cell $sheet "2018-03-02 17:39" -index 0,0

}
$spreadsheet write export5.xlsx
$spreadsheet destroy

Changes to examples/sample6.tcl.

52
53
54
55
56
57
58

59
60
61
62
63
64
65
...
221
222
223
224
225
226
227














228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  set time2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {[$-F400]h:mm:ss\ AM/PM}]]
  set percent [$spreadsheet style -numfmt [$spreadsheet numberformat -percent]]
  set percent2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {0.00%}]]
  set scientific [$spreadsheet style -numfmt [$spreadsheet numberformat -scientific]]
  set fraction [$spreadsheet style -numfmt [$spreadsheet numberformat -fraction]]
  set fraction2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {# ??/??}]]
  set text [$spreadsheet style -numfmt [$spreadsheet numberformat -string]]


  $spreadsheet column $sheet -index 0 -width 17.33203125 -bestfit
  $spreadsheet column $sheet -index 1 -width 20.5 -bestfit
  $spreadsheet column $sheet -index 4 -width 31.1640625 -bestfit
  $spreadsheet column $sheet -index 7 -width 11.1640625 -bestfit ;# -style 19
  $spreadsheet column $sheet -index 8 ;# -style 15

................................................................................
  $spreadsheet cell $sheet {Calibri 18} -index 38,4 -string -style $font18

  $spreadsheet cell $sheet {12 Zellen} -index 39,3 -string -style $hvcenter

  $spreadsheet cell $sheet {3 Spalten} -index 40,0 -string
  $spreadsheet cell $sheet {3 Zeilen} -index 41,1 -string















  $spreadsheet freeze $sheet 20,5

  $spreadsheet autofilter $sheet 19,5 19,6

  $spreadsheet rowheight $sheet 33 20
  $spreadsheet rowheight $sheet 34 20
  $spreadsheet rowheight $sheet 35 20

  $spreadsheet merge $sheet 40,0 40,2
  $spreadsheet merge $sheet 41,1 43,1
  $spreadsheet merge $sheet 39,3 42,5

  $spreadsheet write export6.xlsx
}
$spreadsheet destroy







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>











|
|
<

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

256
  set time2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {[$-F400]h:mm:ss\ AM/PM}]]
  set percent [$spreadsheet style -numfmt [$spreadsheet numberformat -percent]]
  set percent2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {0.00%}]]
  set scientific [$spreadsheet style -numfmt [$spreadsheet numberformat -scientific]]
  set fraction [$spreadsheet style -numfmt [$spreadsheet numberformat -fraction]]
  set fraction2 [$spreadsheet style -numfmt [$spreadsheet numberformat -format {# ??/??}]]
  set text [$spreadsheet style -numfmt [$spreadsheet numberformat -string]]
  set wrap [$spreadsheet style -wrap]

  $spreadsheet column $sheet -index 0 -width 17.33203125 -bestfit
  $spreadsheet column $sheet -index 1 -width 20.5 -bestfit
  $spreadsheet column $sheet -index 4 -width 31.1640625 -bestfit
  $spreadsheet column $sheet -index 7 -width 11.1640625 -bestfit ;# -style 19
  $spreadsheet column $sheet -index 8 ;# -style 15

................................................................................
  $spreadsheet cell $sheet {Calibri 18} -index 38,4 -string -style $font18

  $spreadsheet cell $sheet {12 Zellen} -index 39,3 -string -style $hvcenter

  $spreadsheet cell $sheet {3 Spalten} -index 40,0 -string
  $spreadsheet cell $sheet {3 Zeilen} -index 41,1 -string

  $spreadsheet cell $sheet {this text will be automatically wrapped by excel} -index H27 -style $wrap

  $spreadsheet cell $sheet a -index F21 -style $center
  $spreadsheet cell $sheet a -index F22 -style $center
  $spreadsheet cell $sheet b -index F23 -style $center
  $spreadsheet cell $sheet 1 -index G21 -style $center
  $spreadsheet cell $sheet 2 -index G22 -style $center
  $spreadsheet cell $sheet 2 -index G23 -style $center

  $spreadsheet row $sheet -index 10
  $spreadsheet cell $sheet 3 -index G
  $spreadsheet cell $sheet 5
  $spreadsheet cell $sheet {} -formula G11+H11

  $spreadsheet freeze $sheet 20,5

  $spreadsheet autofilter $sheet 19,5 19,6

  $spreadsheet rowheight $sheet 33 20
  $spreadsheet rowheight $sheet 34 20
  $spreadsheet rowheight $sheet 35 20

  $spreadsheet merge $sheet 40,0 40,2
  $spreadsheet merge $sheet 41,1 43,1
  $spreadsheet merge $sheet 39,3 42,5
}
$spreadsheet write export6.xlsx

$spreadsheet destroy

Deleted examples/sample9.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/sh
#\
exec tclsh8.6 "$0" "$@"

set auto_path [linsert $auto_path 0 ..]
if {[catch {package require ooxml}]} {
  source ../ooxml.tcl
}

set spreadsheet [::ooxml::xl_write new -creator {User A} -created {2019-08-10 10:01:30} -modifiedby {User B} -modified {2019-08-10 12:30:01} -application {Tcl Example Script 9}]
set wrap [$spreadsheet style -wrap]

if {[set sheet [$spreadsheet worksheet {Sheet 1}]] > -1} {
  $spreadsheet cell $sheet {this text will be automatically wrapped by excel} -index A1 -style $wrap
  $spreadsheet write export9.xlsx
}
$spreadsheet destroy
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































Changes to ooxml.tcl.

790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
...
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
...
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
...
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
....
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
....
1418
1419
1420
1421
1422
1423
1424
1425




1426
1427
1428
1429
1430

1431
1432
1433

1434
1435
1436

1437
1438
1439

1440
1441
1442

1443
1444
1445

1446
1447
1448

1449
1450
1451

1452
1453




1454
1455

1456
1457
1458
1459
1460
1461
1462
1463
....
2543
2544
2545
2546
2547
2548
2549
2550




2551
2552





2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564




2565
2566





2567
2568
2569
2570
2571
2572
2573
....
2582
2583
2584
2585
2586
2587
2588
2589




2590
2591

2592



2593

2594
2595
2596
2597
2598
2599
2600
....
2620
2621
2622
2623
2624
2625
2626
2627




2628
2629
2630
2631
2632
2633
2634









2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645




2646
2647





2648
2649
2650
2651
2652
2653
2654
....
2660
2661
2662
2663
2664
2665
2666
2667







2668
2669
2670


2671
2672
2673
2674
2675
2676
2677
....
2682
2683
2684
2685
2686
2687
2688
2689







2690
2691
2692


2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703




2704
2705


2706



2707

2708

2709
2710
2711
2712
2713
2714
2715
....
2833
2834
2835
2836
2837
2838
2839
2840




2841
2842
2843





2844
2845
2846
2847
2848
2849
2850
....
3164
3165
3166
3167
3168
3169
3170
3171




3172
3173

3174



3175

3176
3177
3178
3179
3180
3181
3182
....
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202


3203
3204
3205
3206
3207
3208






3209



3210
3211

3212
3213
3214
3215
3216
3217
3218
3219
....
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
  set mnt [vfs::zip::Mount $file xlsx]

  set rels 0
  if {![catch {open xlsx/xl/_rels/workbook.xml.rels r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} rdoc]} {
      set rels 1
      set relsroot [$rdoc documentElement]
      $rdoc selectNodesNamespaces [list PR $xmlns(PR)]
    }
    close $fd
  }

  if {![catch {open xlsx/xl/workbook.xml r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} doc]} {
      set root [$doc documentElement]
      $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r)]
      set idx -1
      foreach node [$root selectNodes /M:workbook/M:sheets/M:sheet] {
	if {[$node hasAttribute sheetId] && [$node hasAttribute name]} {
	  set sheetId [$node @sheetId]
	  set name [$node @name]
	  set rid [$node getAttributeNS $xmlns(r) id]
	  foreach node [$relsroot selectNodes {/PR:Relationships/PR:Relationship[@Id=$rid]}] {
	    if {[$node hasAttribute Target]} {
	      lappend sheets [incr idx] [list sheetId $sheetId name $name rId $rid]
	    }
	  }
	}
      }
      $doc delete
................................................................................
  set mnt [vfs::zip::Mount $file xlsx]

  set rels 0
  if {![catch {open xlsx/xl/_rels/workbook.xml.rels r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} rdoc]} {
      set rels 1
      set relsroot [$rdoc documentElement]
      $rdoc selectNodesNamespaces [list PR $xmlns(PR)]
    }
    close $fd
  }

  if {![catch {open xlsx/xl/workbook.xml r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} doc]} {
      set root [$doc documentElement]
      $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r)]
      set idx -1
      foreach node [$root selectNodes /M:workbook/M:sheets/M:sheet] {
	if {[$node hasAttribute sheetId] && [$node hasAttribute name]} {
	  set sheetId [$node @sheetId]
	  set name [$node @name]
	  set rid [$node getAttributeNS $xmlns(r) id]
	  foreach node [$relsroot selectNodes {/PR:Relationships/PR:Relationship[@Id=$rid]}] {
	    if {[$node hasAttribute Target]} {
	      lappend sheets [incr idx] $sheetId $name $rid [$node @Target]
	    }
	  }
	}
      }
      $doc delete
................................................................................
  if {$rels} {
    $rdoc delete
  }

  if {![catch {open xlsx/xl/sharedStrings.xml r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} doc]} {
      set root [$doc documentElement]
      $doc selectNodesNamespaces [list M $xmlns(M)]
      set idx -1
      foreach shared [$root selectNodes /M:sst/M:si] {
	incr idx
	foreach node [$shared selectNodes M:t/text()] {
	  append sharedStrings($idx) [$node nodeValue]
	}
................................................................................
    close $fd
  }


  if {![catch {open xlsx/xl/styles.xml r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} doc]} {
      set root [$doc documentElement]
      $doc selectNodesNamespaces [list M $xmlns(M) mc $xmlns(mc) x14ac $xmlns(x14ac) x16r2 $xmlns(x16r2)]
      set idx -1
      foreach node [$root selectNodes /M:styleSheet/M:numFmts/M:numFmt] {
        incr idx
	if {[$node hasAttribute numFmtId] && [$node hasAttribute formatCode]} {
	  set numFmtId [$node @numFmtId]
	  set formatCode [$node @formatCode]
................................................................................
    set wb($sheet,n) $name
    set wb($sheet,max_row) -1
    set wb($sheet,max_column) -1

    if {![catch {open [file join xlsx/xl $target] r} fd]} {
      fconfigure $fd -encoding utf-8
      if {![catch {dom parse [read $fd]} doc]} {
	set root [$doc documentElement]
        $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r) mc $xmlns(mc) x14ac $xmlns(x14ac)]
	set idx -1
	foreach col [$root selectNodes /M:worksheet/M:cols/M:col] {
	  incr idx
	  foreach item {min max width style bestFit customWidth} {
	    if {[$col hasAttribute $item]} {
	      switch -- $item {
................................................................................
    v
    vt:i4 vt:lpstr vt:variant vt:vector
    workbookPr workbookView
    xf
  }

  namespace eval ::ooxml "dom createNodeCmd textNode Text; namespace export Text"





  foreach tag $elementNodes {
    switch -glob -- $tag {
      a:* {
	set ns $xmlns(a)
      }

      cp:* {
	set ns $xmlns(cp)
      }

      dc:* {
	set ns $xmlns(dc)
      }

      dcterms:* {
	set ns $xmlns(dcterms)
      }

      vt:* {
	set ns $xmlns(vt)
      }

      AppVersion - Application - Company - DocSecurity - HeadingPairs - HyperlinksChanged - LinksUpToDate - ScaleCrop - SharedDoc - TitlesOfParts {
	set ns $xmlns(EP)
      }

      Default - Override {
	set ns $xmlns(CT)
      }

      Relationship {
	set ns $xmlns(PR)
      }

      default {
	set ns $xmlns(M)




      }
    }

    namespace eval ::ooxml "dom createNodeCmd -tagName $tag -namespace $ns elementNode Tag_$tag; namespace export Tag_$tag"
  }
  
  set initNodeCmds 1
}


#
................................................................................
        set obj(sharedStrings) 1
	dict set cells($n) v $pos
      }
    }
    unset -nocomplain n v
    array unset lookup
    
    # _rels/.rels




    set doc [dom createDocumentNS $xmlns(PR) Relationships]
    set root [$doc documentElement]






    set rId 0

    $root appendFromScript {
      Tag_Relationship Id rId1 Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument Target xl/workbook.xml {}
      Tag_Relationship Id rId2 Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties Target docProps/app.xml {}
      Tag_Relationship Id rId3 Type http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties Target docProps/core.xml {}
    }
    ::ooxml::Dom2zip $zf $root "_rels/.rels" cd count
    $doc delete

    # [Content_Types].xml




    set doc [dom createDocumentNS $xmlns(CT) Types]
    set root [$doc documentElement]






    $root appendFromScript {
      Tag_Default Extension xml ContentType application/xml {}
      Tag_Default Extension rels ContentType application/vnd.openxmlformats-package.relationships+xml {}
      Tag_Override PartName /xl/workbook.xml ContentType application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml {}
      Tag_Override PartName /xl/worksheets/sheet1.xml ContentType application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml {}
      for {set ws 1} {$ws <= $obj(sheets)} {incr ws} {
................................................................................
      }
      Tag_Override PartName /docProps/core.xml ContentType application/vnd.openxmlformats-package.core-properties+xml {}
      Tag_Override PartName /docProps/app.xml ContentType application/vnd.openxmlformats-officedocument.extended-properties+xml {}
    }
    ::ooxml::Dom2zip $zf $root "\[Content_Types\].xml" cd count
    $doc delete

    # docProps/app.xml




    set doc [set obj(doc,) [dom createDocumentNS $xmlns(EP) Properties]]
    set root [$doc documentElement]





    $root setAttributeNS {} xmlns:vt $xmlns(vt)


    $root appendFromScript {
      Tag_Application { Text $obj(application) }
      Tag_DocSecurity { Text 0 }
      Tag_ScaleCrop { Text false }
      Tag_HeadingPairs {
	Tag_vt:vector size 2 baseType variant {
................................................................................
      Tag_SharedDoc { Text false }
      Tag_HyperlinksChanged { Text false }
      Tag_AppVersion { Text 1.0 }
    }
    ::ooxml::Dom2zip $zf $root "docProps/app.xml" cd count
    $doc delete

    # docProps/core.xml




    set doc [dom createDocumentNS $xmlns(cp) cp:coreProperties]
    set root [$doc documentElement]

    $root setAttributeNS {} xmlns:dc $xmlns(dc)
    $root setAttributeNS {} xmlns:dcterms $xmlns(dcterms)
    $root setAttributeNS {} xmlns:dcmitype $xmlns(dcmitype)
    $root setAttributeNS {} xmlns:xsi $xmlns(xsi)










    $root appendFromScript {
      Tag_dc:creator { Text $obj(creator) }
      Tag_cp:lastModifiedBy { Text $obj(lastModifiedBy) }
      Tag_dcterms:created xsi:type dcterms:W3CDTF { Text $obj(created) }
      Tag_dcterms:modified xsi:type dcterms:W3CDTF { Text $obj(modified) }
    }
    ::ooxml::Dom2zip $zf $root "docProps/core.xml" cd count
    $doc delete

    # xl/_rels/workbook.xml.rels




    set doc [dom createDocumentNS $xmlns(PR) Relationships]
    set root [$doc documentElement]






    $root appendFromScript {
      for {set ws 1} {$ws <= $obj(sheets)} {incr ws} {
	Tag_Relationship Id rId$ws Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet Target worksheets/sheet${ws}.xml {}
      }
      set rId [incr ws -1]
      Tag_Relationship Id rId[incr rId] Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme Target theme/theme1.xml {}
................................................................................
	Tag_Relationship Id rId[incr rId] Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain Target calcChain.xml {}
      }
    }
    ::ooxml::Dom2zip $zf $root "xl/_rels/workbook.xml.rels" cd count
    $doc delete


    # xl/sharedStrings.xml







    if {$obj(sharedStrings) > 0} {
      set doc [dom createDocumentNS $xmlns(M) sst]
      set root [$doc documentElement]



      $root setAttribute count [llength $sharedStrings]
      $root setAttribute uniqueCount [llength $sharedStrings]

      $root appendFromScript {
	foreach string $sharedStrings {
	  Tag_si {
................................................................................
	set sharedStrings {}
      }
      ::ooxml::Dom2zip $zf $root "xl/sharedStrings.xml" cd count
      $doc delete
    }


    # xl/calcChain.xml







    if {$obj(calcChain)} {
      set doc [dom createDocumentNS $xmlns(M) calcChain]
      set root [$doc documentElement]



      $root appendFromScript {
	Tag_c r C1 i 3 l 1 {}
	Tag_c r A3 i 2 {}
      }
      ::ooxml::Dom2zip $zf $root "xl/calcChain.xml" cd count
      $doc delete
    }


    # xl/styles.xml




    set doc [dom createDocumentNS $xmlns(M) styleSheet]
    set root [$doc documentElement]






    $root setAttributeNS {} xmlns:mc $xmlns(mc)

    $root setAttributeNS {} xmlns:x14ac $xmlns(x14ac)

    $root setAttribute mc:Ignorable x14ac

    $root appendFromScript {
      if {$obj(numFmts) > $::ooxml::defaults(numFmts,start)} {
	Tag_numFmts count [llength [array names numFmts]] {
	  foreach idx [lsort -integer [array names numFmts]] {
	    Tag_numFmt numFmtId $idx formatCode $numFmts($idx) {}
................................................................................
      Tag_dxfs count 0 {}
      Tag_tableStyles count 0 {}
    }
    ::ooxml::Dom2zip $zf $root "xl/styles.xml" cd count
    $doc delete


    # xl/theme/theme1.xml




    set doc [dom createDocumentNS $xmlns(a) a:theme]
    set root [$doc documentElement]






    $root setAttribute name Office-Design

    $root appendFromScript {
      Tag_a:themeElements {
	Tag_a:clrScheme name Office {
	  Tag_a:dk1 {
	    Tag_a:sysClr val windowText lastClr 000000 {}
................................................................................
      }
      Tag_a:extraClrSchemeLst {}
    }
    ::ooxml::Dom2zip $zf $root "xl/theme/theme1.xml" cd count
    $doc delete


    # xl/workbook.xml




    set doc [dom createDocumentNS $xmlns(M) workbook]
    set root [$doc documentElement]





    $root setAttributeNS {} xmlns:r $xmlns(r)


    $root appendFromScript {
      Tag_fileVersion appName xl lastEdited 5 lowestEdited 5 rupBuild 5000 {}
      Tag_workbookPr showInkAnnotation 0 autoCompressPictures 0 {}
      Tag_bookViews {
	Tag_workbookView activeTab 1 {}
      }
................................................................................
      Tag_calcPr calcId 140000 concurrentCalc 0 {}
      # fullCalcOnLoad 1
    }
    ::ooxml::Dom2zip $zf $root "xl/workbook.xml" cd count
    $doc delete


    # xl/worksheets/sheet1.xml SHEET

    for {set ws 1} {$ws <= $obj(sheets)} {incr ws} {


      set doc [dom createDocumentNS $xmlns(M) worksheet]
      set root [$doc documentElement]

      $root setAttributeNS {} xmlns:r $xmlns(r)
      $root setAttributeNS {} xmlns:mc $xmlns(mc)
      $root setAttributeNS {} xmlns:x14ac $xmlns(x14ac)






      $root setAttribute mc:Ignorable x14ac




      $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r) mc $xmlns(mc) ac $xmlns(x14ac)]


      $root appendFromScript {
	Tag_dimension ref [::ooxml::RowColumnToString $obj(dminrow,$ws),$obj(dmincol,$ws)]:[::ooxml::RowColumnToString $obj(dmaxrow,$ws),$obj(dmaxcol,$ws)] {}
	Tag_sheetViews {
	  Tag_sheetView workbookViewId 0 {
	    if {$obj(freeze,$ws) ne {}} {
	      lassign [split [::ooxml::StringToRowColumn $obj(freeze,$ws)] ,] row col
	      Tag_pane xSplit $col ySplit $row topLeftCell $obj(freeze,$ws) state frozen {}
................................................................................
	      Tag_mergeCell ref $item {}
	    }
	  }
	}
	Tag_pageMargins left 0.75 right 0.75 top 1 bottom 1 header 0.5 footer 0.5 {}
      }

      if {[set colsNode [$root selectNodes /M:worksheet/M:cols]] ne {}} {
	if {[info exists obj($ws,cols)] && $obj($ws,cols) > 0} {
	  $colsNode appendFromScript {
	    foreach idx [lsort -dictionary [array names cols $ws,*]] {
	      set attr {}
	      lappend attr min [expr {[dict get $cols($idx) min] + 1}] max [expr {[dict get $cols($idx) max] + 1}]
	      if {[dict get $cols($idx) width] ne {}} {
		lappend attr width [dict get $cols($idx) width]







|








|







|







 







|








|







|







 







|







 







|







 







|







 








>
>
>
>
|
|
|
|
<
>
|
|
<
>
|
|
<
>
|
|
<
>
|
|
<
>
|
|
<
>
|
|
<
>
|
|
<
>
|
|
>
>
>
>
|
<
>
|







 







|
>
>
>
>
|
|
>
>
>
>
>











|
>
>
>
>
|
|
>
>
>
>
>







 







|
>
>
>
>
|
|
>

>
>
>
|
>







 







|
>
>
>
>
|
|
<
|
|
|
|
>
>
>
>
>
>
>
>
>










|
>
>
>
>
|
|
>
>
>
>
>







 







|
>
>
>
>
>
>
>

|
|
>
>







 







|
>
>
>
>
>
>
>

|
|
>
>










|
>
>
>
>
|
|
>
>

>
>
>
|
>
|
>







 







|
>
>
>
>



>
>
>
>
>







 







|
>
>
>
>
|
|
>

>
>
>
|
>







 







|

|
>
>
|
|
<
|
|
|
>
>
>
>
>
>
|
>
>
>

<
>








 







|







790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
...
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
...
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
...
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
....
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
....
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436

1437
1438
1439

1440
1441
1442

1443
1444
1445

1446
1447
1448

1449
1450
1451

1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1470
1471
....
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
....
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
....
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668

2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
....
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
....
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
....
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
....
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
....
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309

3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323

3324
3325
3326
3327
3328
3329
3330
3331
3332
....
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
  set mnt [vfs::zip::Mount $file xlsx]

  set rels 0
  if {![catch {open xlsx/xl/_rels/workbook.xml.rels r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} rdoc]} {
      set rels 1
      $rdoc documentElement relsRoot
      $rdoc selectNodesNamespaces [list PR $xmlns(PR)]
    }
    close $fd
  }

  if {![catch {open xlsx/xl/workbook.xml r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} doc]} {
      $doc documentElement root
      $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r)]
      set idx -1
      foreach node [$root selectNodes /M:workbook/M:sheets/M:sheet] {
	if {[$node hasAttribute sheetId] && [$node hasAttribute name]} {
	  set sheetId [$node @sheetId]
	  set name [$node @name]
	  set rid [$node getAttributeNS $xmlns(r) id]
	  foreach node [$relsRoot selectNodes {/PR:Relationships/PR:Relationship[@Id=$rid]}] {
	    if {[$node hasAttribute Target]} {
	      lappend sheets [incr idx] [list sheetId $sheetId name $name rId $rid]
	    }
	  }
	}
      }
      $doc delete
................................................................................
  set mnt [vfs::zip::Mount $file xlsx]

  set rels 0
  if {![catch {open xlsx/xl/_rels/workbook.xml.rels r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} rdoc]} {
      set rels 1
      $rdoc documentElement relsRoot
      $rdoc selectNodesNamespaces [list PR $xmlns(PR)]
    }
    close $fd
  }

  if {![catch {open xlsx/xl/workbook.xml r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} doc]} {
      $doc documentElement root
      $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r)]
      set idx -1
      foreach node [$root selectNodes /M:workbook/M:sheets/M:sheet] {
	if {[$node hasAttribute sheetId] && [$node hasAttribute name]} {
	  set sheetId [$node @sheetId]
	  set name [$node @name]
	  set rid [$node getAttributeNS $xmlns(r) id]
	  foreach node [$relsRoot selectNodes {/PR:Relationships/PR:Relationship[@Id=$rid]}] {
	    if {[$node hasAttribute Target]} {
	      lappend sheets [incr idx] $sheetId $name $rid [$node @Target]
	    }
	  }
	}
      }
      $doc delete
................................................................................
  if {$rels} {
    $rdoc delete
  }

  if {![catch {open xlsx/xl/sharedStrings.xml r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} doc]} {
      $doc documentElement root
      $doc selectNodesNamespaces [list M $xmlns(M)]
      set idx -1
      foreach shared [$root selectNodes /M:sst/M:si] {
	incr idx
	foreach node [$shared selectNodes M:t/text()] {
	  append sharedStrings($idx) [$node nodeValue]
	}
................................................................................
    close $fd
  }


  if {![catch {open xlsx/xl/styles.xml r} fd]} {
    fconfigure $fd -encoding utf-8
    if {![catch {dom parse [read $fd]} doc]} {
      $doc documentElement root
      $doc selectNodesNamespaces [list M $xmlns(M) mc $xmlns(mc) x14ac $xmlns(x14ac) x16r2 $xmlns(x16r2)]
      set idx -1
      foreach node [$root selectNodes /M:styleSheet/M:numFmts/M:numFmt] {
        incr idx
	if {[$node hasAttribute numFmtId] && [$node hasAttribute formatCode]} {
	  set numFmtId [$node @numFmtId]
	  set formatCode [$node @formatCode]
................................................................................
    set wb($sheet,n) $name
    set wb($sheet,max_row) -1
    set wb($sheet,max_column) -1

    if {![catch {open [file join xlsx/xl $target] r} fd]} {
      fconfigure $fd -encoding utf-8
      if {![catch {dom parse [read $fd]} doc]} {
	$doc documentElement root
        $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r) mc $xmlns(mc) x14ac $xmlns(x14ac)]
	set idx -1
	foreach col [$root selectNodes /M:worksheet/M:cols/M:col] {
	  incr idx
	  foreach item {min max width style bestFit customWidth} {
	    if {[$col hasAttribute $item]} {
	      switch -- $item {
................................................................................
    v
    vt:i4 vt:lpstr vt:variant vt:vector
    workbookPr workbookView
    xf
  }

  namespace eval ::ooxml "dom createNodeCmd textNode Text; namespace export Text"

  # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
  # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
  # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
  #
  # foreach tag $elementNodes {
  #   switch -glob -- $tag {
  #     a:* {
  #       set ns $xmlns(a)

  #     }
  #     cp:* {
  #       set ns $xmlns(cp)

  #     }
  #     dc:* {
  #       set ns $xmlns(dc)

  #     }
  #     dcterms:* {
  #       set ns $xmlns(dcterms)

  #     }
  #     vt:* {
  #       set ns $xmlns(vt)

  #     }
  #     AppVersion - Application - Company - DocSecurity - HeadingPairs - HyperlinksChanged - LinksUpToDate - ScaleCrop - SharedDoc - TitlesOfParts {
  #       set ns $xmlns(EP)

  #     }
  #     Default - Override {
  #       set ns $xmlns(CT)

  #     }
  #     Relationship {
  #       set ns $xmlns(PR)

  #     }
  #     default {
  #       set ns $xmlns(M)
  #     }
  #   }
  #   namespace eval ::ooxml "dom createNodeCmd -tagName $tag -namespace $ns elementNode Tag_$tag; namespace export Tag_$tag"
  # }


  foreach tag $elementNodes {
    namespace eval ::ooxml "dom createNodeCmd -tagName $tag elementNode Tag_$tag; namespace export Tag_$tag"
  }
  
  set initNodeCmds 1
}


#
................................................................................
        set obj(sharedStrings) 1
	dict set cells($n) v $pos
      }
    }
    unset -nocomplain n v
    array unset lookup
    
    # ------------------------------ _rels/.rels ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    # set doc [dom createDocumentNS $xmlns(PR) Relationships]
    # set root [$doc documentElement]

    dom createDocument Relationships doc
    $doc documentElement root

    $root setAttribute xmlns $xmlns(PR)

    set rId 0

    $root appendFromScript {
      Tag_Relationship Id rId1 Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument Target xl/workbook.xml {}
      Tag_Relationship Id rId2 Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties Target docProps/app.xml {}
      Tag_Relationship Id rId3 Type http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties Target docProps/core.xml {}
    }
    ::ooxml::Dom2zip $zf $root "_rels/.rels" cd count
    $doc delete

    # ------------------------------ [Content_Types].xml ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    # set doc [dom createDocumentNS $xmlns(CT) Types]
    # set root [$doc documentElement]

    dom createDocument Types doc
    $doc documentElement root

    $root setAttribute xmlns $xmlns(CT)

    $root appendFromScript {
      Tag_Default Extension xml ContentType application/xml {}
      Tag_Default Extension rels ContentType application/vnd.openxmlformats-package.relationships+xml {}
      Tag_Override PartName /xl/workbook.xml ContentType application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml {}
      Tag_Override PartName /xl/worksheets/sheet1.xml ContentType application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml {}
      for {set ws 1} {$ws <= $obj(sheets)} {incr ws} {
................................................................................
      }
      Tag_Override PartName /docProps/core.xml ContentType application/vnd.openxmlformats-package.core-properties+xml {}
      Tag_Override PartName /docProps/app.xml ContentType application/vnd.openxmlformats-officedocument.extended-properties+xml {}
    }
    ::ooxml::Dom2zip $zf $root "\[Content_Types\].xml" cd count
    $doc delete

    # ------------------------------ docProps/app.xml ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    # set doc [dom createDocumentNS $xmlns(EP) Properties]
    # set root [$doc documentElement]
    # $root setAttributeNS {} xmlns:vt $xmlns(vt)

    dom createDocument Properties doc
    $doc documentElement root

    $root setAttribute xmlns $xmlns(EP)
    $root setAttribute xmlns:vt $xmlns(vt)

    $root appendFromScript {
      Tag_Application { Text $obj(application) }
      Tag_DocSecurity { Text 0 }
      Tag_ScaleCrop { Text false }
      Tag_HeadingPairs {
	Tag_vt:vector size 2 baseType variant {
................................................................................
      Tag_SharedDoc { Text false }
      Tag_HyperlinksChanged { Text false }
      Tag_AppVersion { Text 1.0 }
    }
    ::ooxml::Dom2zip $zf $root "docProps/app.xml" cd count
    $doc delete

    # ------------------------------ docProps/core.xml ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    # set doc [dom createDocumentNS $xmlns(cp) cp:coreProperties]
    # set root [$doc documentElement]

    # $root setAttributeNS {} xmlns:dc $xmlns(dc)
    # $root setAttributeNS {} xmlns:dcterms $xmlns(dcterms)
    # $root setAttributeNS {} xmlns:dcmitype $xmlns(dcmitype)
    # $root setAttributeNS {} xmlns:xsi $xmlns(xsi)

    dom createDocument cp:coreProperties doc
    $doc documentElement root

    $root setAttribute xmlns:cp $xmlns(cp)
    $root setAttribute xmlns:dc $xmlns(dc)
    $root setAttribute xmlns:dcterms $xmlns(dcterms)
    $root setAttribute xmlns:dcmitype $xmlns(dcmitype)
    $root setAttribute xmlns:xsi $xmlns(xsi)

    $root appendFromScript {
      Tag_dc:creator { Text $obj(creator) }
      Tag_cp:lastModifiedBy { Text $obj(lastModifiedBy) }
      Tag_dcterms:created xsi:type dcterms:W3CDTF { Text $obj(created) }
      Tag_dcterms:modified xsi:type dcterms:W3CDTF { Text $obj(modified) }
    }
    ::ooxml::Dom2zip $zf $root "docProps/core.xml" cd count
    $doc delete

    # ------------------------------ xl/_rels/workbook.xml.rels ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    # set doc [dom createDocumentNS $xmlns(PR) Relationships]
    # set root [$doc documentElement]

    dom createDocument Relationships doc
    $doc documentElement root

    $root setAttribute xmlns $xmlns(PR)

    $root appendFromScript {
      for {set ws 1} {$ws <= $obj(sheets)} {incr ws} {
	Tag_Relationship Id rId$ws Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet Target worksheets/sheet${ws}.xml {}
      }
      set rId [incr ws -1]
      Tag_Relationship Id rId[incr rId] Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme Target theme/theme1.xml {}
................................................................................
	Tag_Relationship Id rId[incr rId] Type http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain Target calcChain.xml {}
      }
    }
    ::ooxml::Dom2zip $zf $root "xl/_rels/workbook.xml.rels" cd count
    $doc delete


    # ------------------------------ xl/sharedStrings.xml ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    # set doc [dom createDocumentNS $xmlns(M) sst]
    # set root [$doc documentElement]

    if {$obj(sharedStrings) > 0} {
      dom createDocument sst doc
      $doc documentElement root

      $root setAttribute xmlns $xmlns(M)

      $root setAttribute count [llength $sharedStrings]
      $root setAttribute uniqueCount [llength $sharedStrings]

      $root appendFromScript {
	foreach string $sharedStrings {
	  Tag_si {
................................................................................
	set sharedStrings {}
      }
      ::ooxml::Dom2zip $zf $root "xl/sharedStrings.xml" cd count
      $doc delete
    }


    # ------------------------------ xl/calcChain.xml ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    # set doc [dom createDocumentNS $xmlns(M) calcChain]
    # set root [$doc documentElement]

    if {$obj(calcChain)} {
      dom createDocument calcChain doc
      $doc documentElement root

      $root setAttribute xmlns $xmlns(M)

      $root appendFromScript {
	Tag_c r C1 i 3 l 1 {}
	Tag_c r A3 i 2 {}
      }
      ::ooxml::Dom2zip $zf $root "xl/calcChain.xml" cd count
      $doc delete
    }


    # ------------------------------ xl/styles.xml ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    # set doc [dom createDocumentNS $xmlns(M) styleSheet]
    # set root [$doc documentElement]
    # $root setAttributeNS {} xmlns:mc $xmlns(mc)
    # $root setAttributeNS {} xmlns:x14ac $xmlns(x14ac)

    dom createDocument styleSheet doc
    $doc documentElement root

    $root setAttribute xmlns $xmlns(M)
    $root setAttribute xmlns:mc $xmlns(mc)
    $root setAttribute xmlns:x14ac $xmlns(x14ac)

    $root setAttribute mc:Ignorable x14ac

    $root appendFromScript {
      if {$obj(numFmts) > $::ooxml::defaults(numFmts,start)} {
	Tag_numFmts count [llength [array names numFmts]] {
	  foreach idx [lsort -integer [array names numFmts]] {
	    Tag_numFmt numFmtId $idx formatCode $numFmts($idx) {}
................................................................................
      Tag_dxfs count 0 {}
      Tag_tableStyles count 0 {}
    }
    ::ooxml::Dom2zip $zf $root "xl/styles.xml" cd count
    $doc delete


    # ------------------------------ xl/theme/theme1.xml ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    set doc [dom createDocumentNS $xmlns(a) a:theme]
    set root [$doc documentElement]

    dom createDocument a:theme doc
    $doc documentElement root

    $root setAttribute xmlns:a $xmlns(a)

    $root setAttribute name Office-Design

    $root appendFromScript {
      Tag_a:themeElements {
	Tag_a:clrScheme name Office {
	  Tag_a:dk1 {
	    Tag_a:sysClr val windowText lastClr 000000 {}
................................................................................
      }
      Tag_a:extraClrSchemeLst {}
    }
    ::ooxml::Dom2zip $zf $root "xl/theme/theme1.xml" cd count
    $doc delete


    # ------------------------------ xl/workbook.xml ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    # set doc [dom createDocumentNS $xmlns(M) workbook]
    # set root [$doc documentElement]
    # $root setAttributeNS {} xmlns:r $xmlns(r)

    dom createDocument workbook doc
    $doc documentElement root

    $root setAttribute xmlns $xmlns(M)
    $root setAttribute xmlns:r $xmlns(r)

    $root appendFromScript {
      Tag_fileVersion appName xl lastEdited 5 lowestEdited 5 rupBuild 5000 {}
      Tag_workbookPr showInkAnnotation 0 autoCompressPictures 0 {}
      Tag_bookViews {
	Tag_workbookView activeTab 1 {}
      }
................................................................................
      Tag_calcPr calcId 140000 concurrentCalc 0 {}
      # fullCalcOnLoad 1
    }
    ::ooxml::Dom2zip $zf $root "xl/workbook.xml" cd count
    $doc delete


    # ------------------------------ xl/worksheets/sheet1.xml SHEET ------------------------------

    # In the commented out part, serialization is done with namespaces set correctly, but this takes a few milliseconds more time.
    # Since we may process large amounts of data and do not use the same tag names in different namespaces and do not search in
    # the DOM during serialization, we only set the namespaces as attributes, which leads to the same result in the serialized XML.
    # set doc [dom createDocumentNS $xmlns(M) worksheet]
    # set root [$doc documentElement]

    # $root setAttributeNS {} xmlns:r $xmlns(r)
    # $root setAttributeNS {} xmlns:mc $xmlns(mc)
    # $root setAttributeNS {} xmlns:x14ac $xmlns(x14ac)
    # $doc selectNodesNamespaces [list M $xmlns(M) r $xmlns(r) mc $xmlns(mc) ac $xmlns(x14ac)]

    for {set ws 1} {$ws <= $obj(sheets)} {incr ws} {
      dom createDocument worksheet doc
      $doc documentElement root

      $root setAttribute xmlns $xmlns(M)
      $root setAttribute xmlns:r $xmlns(r)
      $root setAttribute xmlns:mc $xmlns(mc)
      $root setAttribute xmlns:x14ac $xmlns(x14ac)


      $root setAttribute mc:Ignorable x14ac

      $root appendFromScript {
	Tag_dimension ref [::ooxml::RowColumnToString $obj(dminrow,$ws),$obj(dmincol,$ws)]:[::ooxml::RowColumnToString $obj(dmaxrow,$ws),$obj(dmaxcol,$ws)] {}
	Tag_sheetViews {
	  Tag_sheetView workbookViewId 0 {
	    if {$obj(freeze,$ws) ne {}} {
	      lassign [split [::ooxml::StringToRowColumn $obj(freeze,$ws)] ,] row col
	      Tag_pane xSplit $col ySplit $row topLeftCell $obj(freeze,$ws) state frozen {}
................................................................................
	      Tag_mergeCell ref $item {}
	    }
	  }
	}
	Tag_pageMargins left 0.75 right 0.75 top 1 bottom 1 header 0.5 footer 0.5 {}
      }

      if {[set colsNode [$root selectNodes /worksheet/cols]] ne {}} {
	if {[info exists obj($ws,cols)] && $obj($ws,cols) > 0} {
	  $colsNode appendFromScript {
	    foreach idx [lsort -dictionary [array names cols $ws,*]] {
	      set attr {}
	      lappend attr min [expr {[dict get $cols($idx) min] + 1}] max [expr {[dict get $cols($idx) max] + 1}]
	      if {[dict get $cols($idx) width] ne {}} {
		lappend attr width [dict get $cols($idx) width]