Index: examples/sample4.tcl ================================================================== --- examples/sample4.tcl +++ examples/sample4.tcl @@ -1,11 +1,13 @@ #!/bin/sh #\ exec tclsh8.6 "$0" "$@" lappend auto_path . -package require ooxml +if {[catch {package require ooxml}]} { + source ../ooxml.tcl +} source array.tcl set spreadsheet [::ooxml::xl_write new -creator {Alexander Schöpe}] if {[set sheet [$spreadsheet worksheet {Tabelle 1}]] > -1} { Index: ooxml.tcl ================================================================== --- ooxml.tcl +++ ooxml.tcl @@ -908,25 +908,27 @@ 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 X [$relsroot namespaceURI]] } 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 X [$root namespaceURI]] set idx -1 - foreach node [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:workbook/X:sheets/X:sheet}] { + foreach node [$root selectNodes /X:workbook/X:sheets/X:sheet] { if {[$node hasAttribute sheetId] && [$node hasAttribute name]} { - set sheetId [$node getAttribute sheetId] - set name [$node getAttribute name] - set rid [$node getAttribute r:id] - foreach node [$relsroot selectNodes -namespaces [list X [$relsroot namespaceURI]] [subst -nobackslashes -nocommands {/X:Relationships/X:Relationship[@Id="$rid"]}]] { + set sheetId [$node @sheetId] + set name [$node @name] + set rid [$node @r:id] + foreach node [$relsroot selectNodes {/X:Relationships/X:Relationship[@Id=$rid]}] { if {[$node hasAttribute Target]} { lappend sheets [incr idx] [list sheetId $sheetId name $name rId $rid] } } } @@ -972,27 +974,29 @@ 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 X [$relsroot namespaceURI]] } 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 X [$root namespaceURI]] set idx -1 - foreach node [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:workbook/X:sheets/X:sheet}] { + foreach node [$root selectNodes /X:workbook/X:sheets/X:sheet] { if {[$node hasAttribute sheetId] && [$node hasAttribute name]} { - set sheetId [$node getAttribute sheetId] - set name [$node getAttribute name] - set rid [$node getAttribute r:id] - foreach node [$relsroot selectNodes -namespaces [list X [$relsroot namespaceURI]] [subst -nobackslashes -nocommands {/X:Relationships/X:Relationship[@Id="$rid"]}]] { + set sheetId [$node @sheetId] + set name [$node @name] + set rid [$node @r:id] + foreach node [$relsroot selectNodes {/X:Relationships/X:Relationship[@Id=$rid]}] { if {[$node hasAttribute Target]} { - lappend sheets [incr idx] $sheetId $name $rid [$node getAttribute Target] + lappend sheets [incr idx] $sheetId $name $rid [$node @Target] } } } } $doc delete @@ -1006,17 +1010,18 @@ 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 X [$root namespaceURI]] set idx -1 - foreach shared [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:sst/X:si}] { + foreach shared [$root selectNodes /X:sst/X:si] { incr idx - foreach node [$shared selectNodes -namespaces [list X [$shared namespaceURI]] {X:t/text()}] { + foreach node [$shared selectNodes X:t/text()] { append sharedStrings($idx) [$node nodeValue] } - foreach node [$shared selectNodes -namespaces [list X [$shared namespaceURI]] {*/X:t/text()}] { + foreach node [$shared selectNodes */X:t/text()] { append sharedStrings($idx) [$node nodeValue] } } $doc delete } @@ -1026,16 +1031,17 @@ 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 X [$root namespaceURI]] set idx -1 - foreach node [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:styleSheet/X:numFmts/X:numFmt}] { + foreach node [$root selectNodes /X:styleSheet/X:numFmts/X:numFmt] { incr idx if {[$node hasAttribute numFmtId] && [$node hasAttribute formatCode]} { - set numFmtId [$node getAttribute numFmtId] - set formatCode [$node getAttribute formatCode] + set numFmtId [$node @numFmtId] + set formatCode [$node @formatCode] set datetime 0 foreach tag {*y* *m* *d* *h* *s*} { if {[string match -nocase $tag [string map {Black {} Blue {} Cyan {} Green {} Magenta {} Red {} White {} Yellow {}} $formatCode]]} { set datetime 1 break @@ -1043,16 +1049,16 @@ } set numFmts($numFmtId) [list dt $datetime fmt $formatCode] } } set idx -1 - foreach node [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:styleSheet/X:cellXfs/X:xf}] { + foreach node [$root selectNodes /X:styleSheet/X:cellXfs/X:xf] { incr idx if {[$node hasAttribute numFmtId]} { - set numFmtId [$node getAttribute numFmtId] + set numFmtId [$node @numFmtId] if {[$node hasAttribute applyNumberFormat]} { - set applyNumberFormat [$node getAttribute applyNumberFormat] + set applyNumberFormat [$node @applyNumberFormat] } else { set applyNumberFormat 0 } set cellXfs($idx) [list nfi $numFmtId anf $applyNumberFormat] } @@ -1063,13 +1069,13 @@ set wb(s,@) {} array unset a * set a(max) 0 set wb(s,numFmtsIds) {} - foreach node [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:styleSheet/X:numFmts/X:numFmt}] { + foreach node [$root selectNodes /X:styleSheet/X:numFmts/X:numFmt] { if {[$node hasAttribute numFmtId] && [$node hasAttribute formatCode]} { - set wb(s,numFmts,[set idx [$node getAttribute numFmtId]]) [$node getAttribute formatCode] + set wb(s,numFmts,[set idx [$node @numFmtId]]) [$node @formatCode] lappend wb(s,numFmtsIds) $idx if {$idx > $a(max)} { set a(max) $idx } } @@ -1080,11 +1086,11 @@ lappend wb(s,@) numFmtId [incr a(max)] set idx -1 array unset a * - foreach node [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:styleSheet/X:fonts/X:font}] { + foreach node [$root selectNodes /X:styleSheet/X:fonts/X:font] { incr idx array set a {name {} family {} size {} color {} scheme {} bold 0 italic 0 underline 0 color {}} foreach node1 [$node childNodes] { switch -- [$node1 nodeName] { b { @@ -1096,37 +1102,37 @@ u { set a(underline) 1 } sz { if {[$node1 hasAttribute val]} { - set a(size) [$node1 getAttribute val] + set a(size) [$node1 @val] } } color { if {[$node1 hasAttribute auto]} { - set a(color) [list auto [$node1 getAttribute auto]] + set a(color) [list auto [$node1 @auto]] } elseif {[$node1 hasAttribute rgb]} { - set a(color) [list rgb [$node1 getAttribute rgb]] + set a(color) [list rgb [$node1 @rgb]] } elseif {[$node1 hasAttribute indexed]} { - set a(color) [list indexed [$node1 getAttribute indexed]] + set a(color) [list indexed [$node1 @indexed]] } elseif {[$node1 hasAttribute theme]} { - set a(color) [list theme [$node1 getAttribute theme]] + set a(color) [list theme [$node1 @theme]] } } name { if {[$node1 hasAttribute val]} { - set a(name) [$node1 getAttribute val] + set a(name) [$node1 @val] } } family { if {[$node1 hasAttribute val]} { - set a(family) [$node1 getAttribute val] + set a(family) [$node1 @val] } } scheme { if {[$node1 hasAttribute val]} { - set a(scheme) [$node1 getAttribute val] + set a(scheme) [$node1 @val] } } } } set wb(s,fonts,$idx) [array get a] @@ -1134,29 +1140,29 @@ lappend wb(s,@) fonts [incr idx] set idx -1 array unset a * - foreach node [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:styleSheet/X:fills/X:fill}] { + foreach node [$root selectNodes /X:styleSheet/X:fills/X:fill] { incr idx array set a {patterntype {} fgcolor {} bgcolor {}} foreach node1 [$node childNodes] { switch -- [$node1 nodeName] { patternFill { if {[$node1 hasAttribute patternType]} { - set a(patterntype) [$node1 getAttribute patternType] + set a(patterntype) [$node1 @patternType] } foreach node2 [$node1 childNodes] { if {[$node2 nodeName] in { fgColor bgColor}} { if {[$node2 hasAttribute auto]} { - set a([string tolower [$node2 nodeName]]) [list auto [$node2 getAttribute auto]] + set a([string tolower [$node2 nodeName]]) [list auto [$node2 @auto]] } elseif {[$node2 hasAttribute rgb]} { - set a([string tolower [$node2 nodeName]]) [list rgb [$node2 getAttribute rgb]] + set a([string tolower [$node2 nodeName]]) [list rgb [$node2 @rgb]] } elseif {[$node2 hasAttribute indexed]} { - set a([string tolower [$node2 nodeName]]) [list indexed [$node2 getAttribute indexed]] + set a([string tolower [$node2 nodeName]]) [list indexed [$node2 @indexed]] } elseif {[$node2 hasAttribute theme]} { - set a([string tolower [$node2 nodeName]]) [list theme [$node2 getAttribute theme]] + set a([string tolower [$node2 nodeName]]) [list theme [$node2 @theme]] } } } } } @@ -1166,30 +1172,30 @@ lappend wb(s,@) fills [incr idx] set idx -1 unset -nocomplain d - foreach node [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:styleSheet/X:borders/X:border}] { + foreach node [$root selectNodes /X:styleSheet/X:borders/X:border] { incr idx set d {left {style {} color {}} right {style {} color {}} top {style {} color {}} bottom {style {} color {}} diagonal {style {} color {} direction {}}} foreach node1 [$node childNodes] { if {[$node1 hasAttribute style]} { - set style [$node1 getAttribute style] + set style [$node1 @style] } else { set style {} } set color {} foreach node2 [$node1 childNodes] { if {[$node2 nodeName] eq {color}} { if {[$node2 hasAttribute auto]} { - set color [list auto [$node2 getAttribute auto]] + set color [list auto [$node2 @auto]] } elseif {[$node2 hasAttribute rgb]} { - set color [list rgb [$node2 getAttribute rgb]] + set color [list rgb [$node2 @rgb]] } elseif {[$node2 hasAttribute indexed]} { - set color [list indexed [$node2 getAttribute indexed]] + set color [list indexed [$node2 @indexed]] } elseif {[$node2 hasAttribute theme]} { - set color [list theme [$node2 getAttribute theme]] + set color [list theme [$node2 @theme]] } } } if {[$node1 nodeName] in {left right top bottom diagonal}} { if {$style ne {}} { @@ -1210,42 +1216,42 @@ lappend wb(s,@) borders [incr idx] set idx -1 array unset a * - foreach node [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:styleSheet/X:cellXfs/X:xf}] { + foreach node [$root selectNodes /X:styleSheet/X:cellXfs/X:xf] { incr idx array set a {numfmt 0 font 0 fill 0 border 0 xf 0 horizontal {} vertical {} rotate {} wrap {}} if {[$node hasAttribute numFmtId]} { - set a(numfmt) [$node getAttribute numFmtId] + set a(numfmt) [$node @numFmtId] } if {[$node hasAttribute fontId]} { - set a(font) [$node getAttribute fontId] + set a(font) [$node @fontId] } if {[$node hasAttribute fillId]} { - set a(fill) [$node getAttribute fillId] + set a(fill) [$node @fillId] } if {[$node hasAttribute borderId]} { - set a(border) [$node getAttribute borderId] + set a(border) [$node @borderId] } if {[$node hasAttribute xfId]} { - set a(xf) [$node getAttribute xfId] + set a(xf) [$node @xfId] } foreach node1 [$node childNodes] { switch -- [$node1 nodeName] { alignment { if {[$node1 hasAttribute horizontal]} { - set a(horizontal) [$node1 getAttribute horizontal] + set a(horizontal) [$node1 @horizontal] } if {[$node1 hasAttribute vertical]} { - set a(vertical) [$node1 getAttribute vertical] + set a(vertical) [$node1 @vertical] } if {[$node1 hasAttribute textRotation]} { - set a(rotate) [$node1 getAttribute textRotation] + set a(rotate) [$node1 @textRotation] } if {[$node1 hasAttribute wrapText]} { - set a(wrap) [$node1 getAttribute wrapText] + set a(wrap) [$node1 @wrapText] } } } } set wb(s,styles,$idx) [array get a] @@ -1289,45 +1295,46 @@ 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 X [$root namespaceURI]] set idx -1 - foreach col [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:worksheet/X:cols/X:col}] { + foreach col [$root selectNodes /X:worksheet/X:cols/X:col] { incr idx foreach item {min max width style bestFit customWidth} { if {[$col hasAttribute $item]} { switch -- $item { min - max { - lappend wb($sheet,col,$idx) [string tolower $item] [expr {[$col getAttribute $item] - 1}] + lappend wb($sheet,col,$idx) [string tolower $item] [expr {[$col @$item] - 1}] } default { - lappend wb($sheet,col,$idx) [string tolower $item] [$col getAttribute $item] + lappend wb($sheet,col,$idx) [string tolower $item] [$col @$item] } } } else { lappend wb($sheet,col,$idx) [string tolower $item] 0 } } lappend wb($sheet,col,$idx) string 0 nozero 0 calcfit 0 } set wb($sheet,cols) [incr idx] - foreach cell [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:worksheet/X:sheetData/X:row/X:c}] { + foreach cell [$root selectNodes /X:worksheet/X:sheetData/X:row/X:c] { if {[$cell hasAttribute t]} { - set type [$cell getAttribute t] + set type [$cell @t] } else { set type n } set value {} set datetime {} switch -- $type { n - b - d - str { # number (default), boolean, iso-date, formula string - if {[set node [$cell selectNodes -namespaces [list X [$cell namespaceURI]] X:v/text()]] ne {}} { + if {[set node [$cell selectNodes X:v/text()]] ne {}} { set value [$node nodeValue] if {$type eq {n} && [$cell hasAttribute s] && [string is double -strict $value]} { - set idx [$cell getAttribute s] + set idx [$cell @s] if {[dict exists $cellXfs($idx) nfi]} { set numFmtId [dict get $cellXfs($idx) nfi] if {[info exists numFmts($numFmtId)] && [dict exists $numFmts($numFmtId) dt] && [dict get $numFmts($numFmtId) dt]} { set datetime $value catch {clock format [expr {int(($value - 25569) * 86400.0)}] -format $opts(datefmt) -gmt 1} value @@ -1338,11 +1345,11 @@ if {![$cell hasAttribute s]} continue } } s { # shared string - if {[set node [$cell selectNodes -namespaces [list X [$cell namespaceURI]] X:v/text()]] ne {}} { + if {[set node [$cell selectNodes X:v/text()]] ne {}} { set index [$node nodeValue] if {[info exists sharedStrings($index)]} { set value $sharedStrings($index) } } else { @@ -1349,15 +1356,15 @@ if {![$cell hasAttribute s]} continue } } inlineStr { # inline string - if {[set string [$cell selectNodes -namespaces [list X [$cell namespaceURI]] X:is]] ne {}} { - foreach node [$string selectNodes -namespaces [list X [$string namespaceURI]] {X:t/text()}] { + if {[set string [$cell selectNodes X:is]] ne {}} { + foreach node [$string selectNodes X:t/text()] { append value [$node nodeValue] } - foreach node [$string selectNodes -namespaces [list X [$string namespaceURI]] {*/X:t/text()}] { + foreach node [$string selectNodes */X:t/text()] { append value [$node nodeValue] } } else { if {![$cell hasAttribute s]} continue } @@ -1367,56 +1374,56 @@ } } if {[$cell hasAttribute r]} { if {!$opts(valuesonly)} { - set wb($sheet,c,[StringToRowColumn [$cell getAttribute r]]) [$cell getAttribute r] + set wb($sheet,c,[StringToRowColumn [$cell @r]]) [$cell @r] } if {!$opts(valuesonly)} { if {[$cell hasAttribute s]} { - set wb($sheet,s,[StringToRowColumn [$cell getAttribute r]]) [$cell getAttribute s] + set wb($sheet,s,[StringToRowColumn [$cell @r]]) [$cell @s] } } if {!$opts(valuesonly)} { if {[$cell hasAttribute t]} { - set wb($sheet,t,[StringToRowColumn [$cell getAttribute r]]) [$cell getAttribute t] - } - } - set wb($sheet,v,[StringToRowColumn [$cell getAttribute r]]) $value - if {!$opts(valuesonly) && $datetime ne {}} { - set wb($sheet,d,[StringToRowColumn [$cell getAttribute r]]) $datetime - } - if {!$opts(valuesonly) && [set node [$cell selectNodes -namespaces [list X [$cell namespaceURI]] X:f/text()]] ne {}} { - set wb($sheet,f,[StringToRowColumn [$cell getAttribute r]]) [$node nodeValue] - } - } - } - if {!$opts(valuesonly)} { - foreach row [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:worksheet/X:sheetData/X:row}] { - if {[$row hasAttribute r] && [$row hasAttribute ht] && [$row hasAttribute customHeight] && [$row getAttribute customHeight] == 1} { - dict set wb($sheet,rowheight) [expr {[$row getAttribute r] - 1}] [$row getAttribute ht] - } - } - } - if {!$opts(valuesonly)} { - foreach freeze [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:worksheet/X:sheetViews/X:sheetView/X:pane}] { - if {[$freeze hasAttribute topLeftCell] && [$freeze hasAttribute state] && [$freeze getAttribute state] eq {frozen}} { - set wb($sheet,freeze) [$freeze getAttribute topLeftCell] - } - } - } - if {!$opts(valuesonly)} { - foreach filter [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:worksheet/X:autoFilter}] { - if {[$filter hasAttribute ref]} { - lappend wb($sheet,filter) [$filter getAttribute ref] - } - } - } - if {!$opts(valuesonly)} { - foreach merge [$root selectNodes -namespaces [list X [$root namespaceURI]] {/X:worksheet/X:mergeCells/X:mergeCell}] { - if {[$merge hasAttribute ref]} { - lappend wb($sheet,merge) [$merge getAttribute ref] + set wb($sheet,t,[StringToRowColumn [$cell @r]]) [$cell @t] + } + } + set wb($sheet,v,[StringToRowColumn [$cell @r]]) $value + if {!$opts(valuesonly) && $datetime ne {}} { + set wb($sheet,d,[StringToRowColumn [$cell @r]]) $datetime + } + if {!$opts(valuesonly) && [set node [$cell selectNodes X:f/text()]] ne {}} { + set wb($sheet,f,[StringToRowColumn [$cell @r]]) [$node nodeValue] + } + } + } + if {!$opts(valuesonly)} { + foreach row [$root selectNodes /X:worksheet/X:sheetData/X:row] { + if {[$row hasAttribute r] && [$row hasAttribute ht] && [$row hasAttribute customHeight] && [$row @customHeight] == 1} { + dict set wb($sheet,rowheight) [expr {[$row @r] - 1}] [$row @ht] + } + } + } + if {!$opts(valuesonly)} { + foreach freeze [$root selectNodes /X:worksheet/X:sheetViews/X:sheetView/X:pane] { + if {[$freeze hasAttribute topLeftCell] && [$freeze hasAttribute state] && [$freeze @state] eq {frozen}} { + set wb($sheet,freeze) [$freeze @topLeftCell] + } + } + } + if {!$opts(valuesonly)} { + foreach filter [$root selectNodes /X:worksheet/X:autoFilter] { + if {[$filter hasAttribute ref]} { + lappend wb($sheet,filter) [$filter @ref] + } + } + } + if {!$opts(valuesonly)} { + foreach merge [$root selectNodes /X:worksheet/X:mergeCells/X:mergeCell] { + if {[$merge hasAttribute ref]} { + lappend wb($sheet,merge) [$merge @ref] } } } $doc delete } @@ -3007,11 +3014,11 @@ } } 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 {[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}] @@ -3202,5 +3209,9 @@ } } } package provide ooxml 1.2 + +# Local Variables: +# tcl-indent-level: 2 +# End: