├── .haxerc ├── tests.hxml ├── .gitignore ├── haxe_libraries ├── openxml.hxml ├── ansi.hxml ├── format.hxml ├── tink_chunk.hxml ├── tink_core.hxml ├── tink_priority.hxml ├── tink_macro.hxml ├── travix.hxml ├── tink_testrunner.hxml ├── hxnodejs.hxml ├── tink_syntaxhub.hxml ├── tink_unittest.hxml ├── xml-writer.hxml ├── archive.hxml ├── tink_io.hxml └── tink_streams.hxml ├── Run.bat ├── lib ├── System.Xml.dll └── System.Xml.Linq.dll ├── .gitmodules ├── src └── openxml │ ├── util │ ├── IXml.hx │ ├── Color.hx │ ├── XmlArray.hx │ └── XmlTools.hx │ ├── spreadsheet │ ├── style │ │ ├── NumberFormat.hx │ │ ├── Border.hx │ │ ├── Font.hx │ │ ├── Styles.hx │ │ ├── Format.hx │ │ └── Fill.hx │ ├── Row.hx │ ├── SharedStrings.hx │ ├── Workbook.hx │ ├── Worksheet.hx │ ├── Writer.hx │ └── Cell.hx │ ├── CoreProperties.hx │ ├── XmlNameSpaces.hx │ ├── Relationships.hx │ ├── wordprocessing │ ├── Writer.hx │ └── Document.hx │ ├── ExtendedProperties.hx │ └── ContentTypes.hx ├── validator.hxml ├── package.json ├── haxelib.json ├── test ├── Wordprocessing.hx └── Spreadsheet.hx ├── tests ├── RunTests.hx ├── TestWordprocessing.hx ├── TestSpreadsheet.hx └── Validator.hx ├── .vscode ├── settings.json └── tasks.json ├── LICENSE ├── appveyor.yml ├── README.md ├── .travis.yml └── yarn.lock /.haxerc: -------------------------------------------------------------------------------- 1 | {"version":"3.4.4","resolveLibs":"scoped"} -------------------------------------------------------------------------------- /tests.hxml: -------------------------------------------------------------------------------- 1 | -cp tests 2 | -main RunTests 3 | -lib tink_unittest -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.hxproj 2 | bin/ 3 | assets/ 4 | ref/ 5 | node_modules -------------------------------------------------------------------------------- /haxe_libraries/openxml.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | 3 | -lib xml-writer 4 | -lib archive -------------------------------------------------------------------------------- /Run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd bin 3 | neko spreadsheet.n 4 | neko wordprocessing.n 5 | pause 6 | -------------------------------------------------------------------------------- /lib/System.Xml.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinresol/openxml/HEAD/lib/System.Xml.dll -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "sdk"] 2 | path = sdk 3 | url = https://github.com/OfficeDev/Open-XML-SDK 4 | -------------------------------------------------------------------------------- /lib/System.Xml.Linq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinresol/openxml/HEAD/lib/System.Xml.Linq.dll -------------------------------------------------------------------------------- /src/openxml/util/IXml.hx: -------------------------------------------------------------------------------- 1 | package openxml.util; 2 | 3 | /** 4 | * @author Kevin 5 | */ 6 | 7 | interface IXml 8 | { 9 | function toXml():Xml; 10 | } -------------------------------------------------------------------------------- /haxe_libraries/ansi.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:ansi#1.0.0" into ansi/1.0.0/haxelib 2 | -D ansi=1.0.0 3 | -cp ${HAXESHIM_LIBCACHE}/ansi/1.0.0/haxelib/src 4 | -------------------------------------------------------------------------------- /haxe_libraries/format.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:format#3.4.0" into format/3.4.0/haxelib 2 | -D format=3.4.0 3 | -cp ${HAXESHIM_LIBCACHE}/format/3.4.0/haxelib/ 4 | -------------------------------------------------------------------------------- /haxe_libraries/tink_chunk.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:tink_chunk#0.2.0" into tink_chunk/0.2.0/haxelib 2 | -D tink_chunk=0.2.0 3 | -cp ${HAXESHIM_LIBCACHE}/tink_chunk/0.2.0/haxelib/src 4 | -------------------------------------------------------------------------------- /haxe_libraries/tink_core.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:tink_core#1.15.3" into tink_core/1.15.3/haxelib 2 | -D tink_core=1.15.3 3 | -cp ${HAXESHIM_LIBCACHE}/tink_core/1.15.3/haxelib/src 4 | -------------------------------------------------------------------------------- /haxe_libraries/tink_priority.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:tink_priority#0.1.3" into tink_priority/0.1.3/haxelib 2 | -D tink_priority=0.1.3 3 | -cp ${HAXESHIM_LIBCACHE}/tink_priority/0.1.3/haxelib/src 4 | -------------------------------------------------------------------------------- /haxe_libraries/tink_macro.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:tink_macro#0.15.4" into tink_macro/0.15.4/haxelib 2 | -D tink_macro=0.15.4 3 | -cp ${HAXESHIM_LIBCACHE}/tink_macro/0.15.4/haxelib/src 4 | 5 | -lib tink_core -------------------------------------------------------------------------------- /validator.hxml: -------------------------------------------------------------------------------- 1 | -cp tests 2 | -main Validator 3 | -cs bin/validator 4 | 5 | -D net-ver=40 6 | 7 | -net-lib sdk/DocumentFormat.OpenXml/bin/Release/DocumentFormat.OpenXml.dll 8 | -net-lib sdk/System.IO.Packaging/bin/Release/System.IO.Packaging.dll -------------------------------------------------------------------------------- /haxe_libraries/travix.hxml: -------------------------------------------------------------------------------- 1 | # @run: haxelib run-dir travix ${HAXESHIM_LIBCACHE}/travix/0.10.3/haxelib 2 | # @install: lix --silent download "haxelib:travix#0.10.3" into travix/0.10.3/haxelib 3 | -D travix=0.10.3 4 | -cp ${HAXESHIM_LIBCACHE}/travix/0.10.3/haxelib/src 5 | -------------------------------------------------------------------------------- /haxe_libraries/tink_testrunner.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:tink_testrunner#0.6.2" into tink_testrunner/0.6.2/haxelib 2 | -D tink_testrunner=0.6.2 3 | -cp ${HAXESHIM_LIBCACHE}/tink_testrunner/0.6.2/haxelib/src 4 | 5 | -lib ansi 6 | -lib tink_macro 7 | -lib tink_streams -------------------------------------------------------------------------------- /haxe_libraries/hxnodejs.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:hxnodejs#4.0.9" into hxnodejs/4.0.9/haxelib 2 | -D hxnodejs=4.0.9 3 | -cp ${HAXESHIM_LIBCACHE}/hxnodejs/4.0.9/haxelib/src 4 | -D nodejs 5 | --macro allowPackage('sys') 6 | --macro _hxnodejs.VersionWarning.include() 7 | -------------------------------------------------------------------------------- /haxe_libraries/tink_syntaxhub.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:tink_syntaxhub#0.3.6" into tink_syntaxhub/0.3.6/haxelib 2 | -D tink_syntaxhub=0.3.6 3 | -cp ${HAXESHIM_LIBCACHE}/tink_syntaxhub/0.3.6/haxelib/src 4 | --macro tink.SyntaxHub.use() 5 | -lib tink_priority 6 | -lib tink_macro -------------------------------------------------------------------------------- /haxe_libraries/tink_unittest.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:tink_unittest#0.5.5" into tink_unittest/0.5.5/haxelib 2 | -D tink_unittest=0.5.5 3 | -cp ${HAXESHIM_LIBCACHE}/tink_unittest/0.5.5/haxelib/src 4 | --macro tink.unit.AssertionBufferInjector.use() 5 | -lib tink_syntaxhub 6 | -lib tink_testrunner -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "haxelib": "haxelib", 4 | "haxe": "haxe", 5 | "travix": "travix", 6 | "postinstall": "lix download" 7 | }, 8 | "dependencies": { 9 | "archiver": "^2.1.1", 10 | "haxe-travix": "^0.10.2", 11 | "haxeshim": "^0.12.2", 12 | "lix.pm": "^0.14.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /haxe_libraries/xml-writer.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "https://github.com/kevinresol/xml-writer/archive/d207cf0ec883b25584fbb87cbdd73d483e040d73.tar.gz" into xml-writer/0.0.0/github/d207cf0ec883b25584fbb87cbdd73d483e040d73 2 | -D xml-writer=0.0.0 3 | -cp ${HAXESHIM_LIBCACHE}/xml-writer/0.0.0/github/d207cf0ec883b25584fbb87cbdd73d483e040d73/src 4 | -------------------------------------------------------------------------------- /haxe_libraries/archive.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "https://github.com/kevinresol/archive/archive/be767d1eccee05b9d80f05d3d040264ba4ca6e6e.tar.gz" into archive/0.0.0/github/be767d1eccee05b9d80f05d3d040264ba4ca6e6e 2 | -D archive=0.0.0 3 | -cp ${HAXESHIM_LIBCACHE}/archive/0.0.0/github/be767d1eccee05b9d80f05d3d040264ba4ca6e6e/src 4 | 5 | -lib tink_io 6 | -lib format -------------------------------------------------------------------------------- /haxe_libraries/tink_io.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "https://github.com/haxetink/tink_io/archive/7b92d1a3ac9e7c031c16f04dec96e35926b5bfcb.tar.gz" into tink_io/0.0.0/github/7b92d1a3ac9e7c031c16f04dec96e35926b5bfcb 2 | -D tink_io=0.0.0 3 | -cp ${HAXESHIM_LIBCACHE}/tink_io/0.0.0/github/7b92d1a3ac9e7c031c16f04dec96e35926b5bfcb/src 4 | 5 | -lib tink_chunk 6 | -lib tink_streams -------------------------------------------------------------------------------- /haxelib.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openxml", 3 | "url": "https://github.com/kevinresol/openxml", 4 | "license": "MIT", 5 | "contributors": ["kevinresol"], 6 | "description": "A Haxe implemention of Office Open XML", 7 | "version": "0.0.1", 8 | "classPath": "src", 9 | "releasenote": "Alpha", 10 | "dependencies": { 11 | "xml-writer": "", 12 | "archive": "" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /haxe_libraries/tink_streams.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "https://github.com/haxetink/tink_streams/archive/0e7555ff2310cfe0ee87d0e1e9c94803724b9958.tar.gz" into tink_streams/0.2.1/github/0e7555ff2310cfe0ee87d0e1e9c94803724b9958 2 | -D tink_streams=0.2.1 3 | -cp ${HAXESHIM_LIBCACHE}/tink_streams/0.2.1/github/0e7555ff2310cfe0ee87d0e1e9c94803724b9958/src 4 | # temp for development, delete this file when pure branch merged 5 | -D pure 6 | -lib tink_core -------------------------------------------------------------------------------- /test/Wordprocessing.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import openxml.wordprocessing.Document; 4 | import openxml.wordprocessing.Writer; 5 | 6 | /** 7 | * ... 8 | * @author Kevin 9 | */ 10 | 11 | class Wordprocessing { 12 | 13 | static function main() { 14 | var doc = new Document(); 15 | doc.body.addParagraph("My paragraph."); 16 | 17 | var w = new Writer(new archive.zip.NodeZip()); 18 | w.write(doc).pipeTo(tink.io.Sink.ofNodeStream('name', js.node.Fs.createWriteStream('output.docx'))) 19 | .handle(function(o) { 20 | trace(o); 21 | Sys.exit(0); 22 | }); 23 | } 24 | } -------------------------------------------------------------------------------- /tests/RunTests.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import tink.unit.*; 4 | import tink.testrunner.*; 5 | 6 | class RunTests { 7 | 8 | static function main() { 9 | 10 | Runner.run(TestBatch.make([ 11 | new TestSpreadsheet(), 12 | new TestWordprocessing(), 13 | ])).handle(Runner.exit); 14 | } 15 | 16 | public static function runValidator(type:String, path:String) { 17 | trace(Sys.getCwd()); 18 | return switch Sys.systemName() { 19 | case 'Windows': Sys.command('"./bin/validator/bin/Validator.exe"', [type, path]); 20 | default: Sys.command('mono', ['./bin/validator/bin/Validator.exe', type, path]); 21 | } 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // These are configurations used for haxe completion. 3 | // 4 | // Each configuration is an array of arguments that will be passed to the Haxe completion server, 5 | // they should only contain arguments and/or hxml files that are needed for completion, 6 | // such as -cp, -lib, target output settings and defines. 7 | "haxe.displayConfigurations": [ 8 | ["build.hxml"], // if a hxml file is safe to use, we can just pass it as argument 9 | // you can add more than one configuration and switch between them 10 | ["tests.hxml"], 11 | ["validator.hxml"] 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/openxml/util/Color.hx: -------------------------------------------------------------------------------- 1 | package openxml.util; 2 | 3 | import xml.*; 4 | 5 | /** 6 | * ... 7 | * @author ... 8 | */ 9 | class Color implements IXml { 10 | public var auto:Null; 11 | public var argb:Null; 12 | 13 | var elementName:String; 14 | 15 | public function new(elementName:String) { 16 | this.elementName = elementName; 17 | } 18 | 19 | public function toXml():Xml { 20 | var xc = new Element(elementName); 21 | 22 | if (auto != null) xc.setAttribute('auto', auto); 23 | if (argb != null) xc.setAttribute('rgb', StringTools.hex(argb)); 24 | 25 | return xc; 26 | } 27 | 28 | } 29 | 30 | enum ColorType { 31 | 32 | } -------------------------------------------------------------------------------- /tests/TestWordprocessing.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import openxml.wordprocessing.Document; 4 | import openxml.wordprocessing.Writer; 5 | 6 | @:asserts 7 | class TestWordprocessing { 8 | public function new() {} 9 | 10 | public function testOutput() { 11 | var doc = new Document(); 12 | doc.body.addParagraph("My paragraph."); 13 | 14 | var path = 'bin/output.docx'; 15 | 16 | var w = new Writer(new archive.zip.NodeZip()); 17 | var path = 'bin/output.docx'; 18 | w.write(doc).pipeTo(tink.io.Sink.ofNodeStream('name', js.node.Fs.createWriteStream(path))) 19 | .handle(function(o) { 20 | asserts.assert(RunTests.runValidator('wordprocessing', path) == 0); 21 | asserts.done(); 22 | }); 23 | 24 | return asserts; 25 | } 26 | } -------------------------------------------------------------------------------- /src/openxml/spreadsheet/style/NumberFormat.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet.style; 2 | 3 | import xml.*; 4 | import openxml.util.IXml; 5 | import openxml.util.XmlArray; 6 | 7 | /** 8 | * ... 9 | * @author ... 10 | */ 11 | class NumberFormats extends XmlArray { 12 | 13 | public function new() { 14 | super('numberFormats'); 15 | addNumberFormat(); 16 | } 17 | 18 | public function addNumberFormat():NumberFormat { 19 | var numberFormat = new NumberFormat(); 20 | push(numberFormat); 21 | return numberFormat; 22 | } 23 | } 24 | 25 | class NumberFormat implements IXmlArrayItem { 26 | public var id:Int; 27 | public function new() { 28 | 29 | } 30 | 31 | public function toXml():Xml { 32 | return new Element('numberFormat'); 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/openxml/CoreProperties.hx: -------------------------------------------------------------------------------- 1 | package openxml; 2 | 3 | import xml.*; 4 | import openxml.util.IXml; 5 | 6 | /** 7 | * ... 8 | * @author Kevin 9 | */ 10 | class CoreProperties extends Document implements IXml { 11 | public function new() { 12 | super( 13 | new ProcessingInstruction('xml version="1.0" encoding="UTF-8"'), 14 | new Element('cp:coreProperties') 15 | .setAttribute('xmlns:cp', "http://schemas.openxmlformats.org/package/2006/metadata/core-properties") 16 | .setAttribute('xmlns:dc', "http://purl.org/dc/elements/1.1/") 17 | .setAttribute('xmlns:dcmitype', "http://purl.org/dc/dcmitype/") 18 | .setAttribute('xmlns:dcterms', "http://purl.org/dc/terms/") 19 | .setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance") 20 | ); 21 | } 22 | } -------------------------------------------------------------------------------- /src/openxml/spreadsheet/Row.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet; 2 | 3 | import xml.*; 4 | import openxml.spreadsheet.Cell; 5 | import openxml.util.IXml; 6 | 7 | /** 8 | * ... 9 | * @author Kevin 10 | */ 11 | class Row implements IXml { 12 | public var row:Int; 13 | 14 | var cells:Array; 15 | 16 | public function new(row:Int) { 17 | this.row = row; 18 | cells = []; 19 | } 20 | 21 | public function addCell(cell:Cell) { 22 | if(cells.indexOf(cell) == -1) 23 | cells.push(cell); 24 | } 25 | 26 | public function toXml():Xml { 27 | var xr = new Element('row') 28 | .setAttribute('r', row + 1); 29 | 30 | cells.sort(function(c1, c2) return c1.col - c2.col); 31 | for (cell in cells) { 32 | var xc = cell.toXml(); 33 | if (xc != null) xr.add(xc); 34 | } 35 | 36 | return xr; 37 | } 38 | } -------------------------------------------------------------------------------- /src/openxml/spreadsheet/style/Border.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet.style; 2 | 3 | import xml.*; 4 | import openxml.util.XmlArray; 5 | 6 | /** 7 | * ... 8 | * @author ... 9 | */ 10 | class Borders extends XmlArray { 11 | 12 | public function new() { 13 | super('borders'); 14 | 15 | addBorder(); 16 | } 17 | 18 | public function addBorder():Border { 19 | var border = new Border(); 20 | push(border); 21 | return border; 22 | } 23 | } 24 | 25 | class Border implements IXmlArrayItem { 26 | public var id:Int; 27 | 28 | public function new() {} 29 | 30 | public function toXml():Xml { 31 | return new Element('border') 32 | .add(new Element('left')) 33 | .add(new Element('right')) 34 | .add(new Element('top')) 35 | .add(new Element('bottom')) 36 | .add(new Element('diagonal')); 37 | } 38 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "command": "haxe", 4 | "args": ["build.hxml"], 5 | "problemMatcher": { 6 | "owner": "haxe", 7 | "pattern": { 8 | "regexp": "^(.+):(\\d+): (?:lines \\d+-(\\d+)|character(?:s (\\d+)-| )(\\d+)) : (?:(Warning) : )?(.*)$", 9 | "file": 1, 10 | "line": 2, 11 | "endLine": 3, 12 | "column": 4, 13 | "endColumn": 5, 14 | "severity": 6, 15 | "message": 7 16 | } 17 | }, 18 | "tasks": [ 19 | { 20 | "type": "hxml", 21 | "file": "build.hxml", 22 | "problemMatcher": [ 23 | "$haxe" 24 | ], 25 | "group": { 26 | "kind": "build", 27 | "isDefault": true 28 | } 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /src/openxml/XmlNameSpaces.hx: -------------------------------------------------------------------------------- 1 | package openxml; 2 | 3 | /** 4 | * ... 5 | * @author Kevin 6 | */ 7 | class XmlNameSpaces 8 | { 9 | public static var spreadsheetml = SpreadsheetML; 10 | public static var wordprocessingml = WordprocessingML; 11 | public static var officeDocument = OfficeDocument; 12 | public static var pack = Package; 13 | } 14 | 15 | private class SpreadsheetML 16 | { 17 | public static inline var MAIN = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; 18 | } 19 | 20 | private class WordprocessingML 21 | { 22 | public static inline var MAIN = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"; 23 | } 24 | 25 | private class OfficeDocument 26 | { 27 | public static inline var RELATIONSHIPS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"; 28 | } 29 | 30 | private class Package 31 | { 32 | public static inline var RELATIONSHIPS = 'http://schemas.openxmlformats.org/package/2006/relationships'; 33 | public static inline var CONTENT_TYPES = 'http://schemas.openxmlformats.org/package/2006/content-types'; 34 | 35 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Kevin Leung 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | environment: 4 | global: 5 | HAXELIB_ROOT: C:\projects\haxelib 6 | 7 | install: 8 | # Install the haxe chocolatey package (https://chocolatey.org/packages/haxe) 9 | - cinst haxe -version 3.2.1 -y 10 | - RefreshEnv 11 | # Setup haxelib 12 | - mkdir "%HAXELIB_ROOT%" 13 | - haxelib setup "%HAXELIB_ROOT%" 14 | # `> log.txt || type log.txt` is for muting the output unless there is an error 15 | - haxelib install travix > log.txt || type log.txt && cmd /C exit 1 16 | - haxelib install hxcs > log.txt || type log.txt && cmd /C exit 1 17 | - haxelib list 18 | - haxelib run travix install 19 | - ps: $env:HXCS_PATH = haxelib path hxcs | Select-Object -First 1 20 | - copy "C:\Program Files (x86)\Mono\lib\mono\4.0\System.Xml.Linq.dll" "%HXCS_PATH%\netlib\net-40\" 21 | - copy "C:\Program Files (x86)\Mono\lib\mono\4.0\System.Xml.dll" "%HXCS_PATH%\netlib\net-40\" 22 | - git submodule sync && git submodule update --init --recursive && git submodule status 23 | - cd sdk 24 | - ps: $content = get-content build.open-xml-sdk.cmd | select-string -pattern "xunit`.console`.exe" -notmatch 25 | - ps: $content | set-content build.open-xml-sdk.cmd -Force 26 | - build.open-xml-sdk.cmd 27 | - cd .. 28 | 29 | build: off 30 | test_script: 31 | - haxe validator.hxml 32 | - haxelib run travix neko -------------------------------------------------------------------------------- /src/openxml/util/XmlArray.hx: -------------------------------------------------------------------------------- 1 | package openxml.util; 2 | 3 | using openxml.util.XmlTools; 4 | /** 5 | * ... 6 | * @author ... 7 | */ 8 | class XmlArray implements IXml 9 | { 10 | public var length(get, never):Int; 11 | 12 | var array:Array; 13 | var elementName:String; 14 | 15 | public function new(elementName:String) 16 | { 17 | array = []; 18 | this.elementName = elementName; 19 | } 20 | 21 | public function push(item:T):Int 22 | { 23 | var i = array.push(item); 24 | item.id = i - 1; 25 | return i; 26 | } 27 | 28 | public inline function pop():T 29 | { 30 | return array.pop(); 31 | } 32 | 33 | public inline function remove(item:T):Bool 34 | { 35 | var r = array.remove(item); 36 | 37 | if (r) 38 | for (i in 0...array.length) 39 | array[i].id = i; 40 | 41 | return r; 42 | } 43 | 44 | public inline function iterator() 45 | { 46 | return array.iterator(); 47 | } 48 | 49 | public function toXml():Xml 50 | { 51 | var xml = Xml.createElement(elementName); 52 | xml.set('count', Std.string(array.length)); 53 | for (i in array) 54 | xml.addChild(i.toXml()); 55 | return xml; 56 | } 57 | 58 | private inline function get_length():Int 59 | { 60 | return array.length; 61 | } 62 | 63 | } 64 | 65 | interface IXmlArrayItem extends IXml 66 | { 67 | var id:Int; 68 | } -------------------------------------------------------------------------------- /src/openxml/spreadsheet/style/Font.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet.style; 2 | 3 | import xml.*; 4 | import openxml.util.IXml; 5 | import openxml.util.XmlArray; 6 | 7 | /** 8 | * ... 9 | * @author ... 10 | */ 11 | class Fonts extends XmlArray { 12 | 13 | public function new() { 14 | super('fonts'); 15 | addFont(); 16 | } 17 | 18 | public function addFont():Font { 19 | var font = new Font(); 20 | push(font); 21 | return font; 22 | } 23 | 24 | 25 | } 26 | 27 | @:allow(openxml.spreadsheet) 28 | class Font implements IXml implements IXmlArrayItem { 29 | public var bold:Bool = false; 30 | public var italic:Bool = false; 31 | public var size:Int = 8; 32 | public var family:Int = 0; 33 | public var name:String = "Arial"; 34 | 35 | public var id:Int; 36 | 37 | function new() {} 38 | 39 | public function toXml():Xml { 40 | var xml = new Element('font'); 41 | 42 | if (bold) xml.add(new Element('b')); 43 | if (italic) xml.add(new Element('i')); 44 | 45 | xml 46 | .add( 47 | new Element('sz') 48 | .setAttribute('val', Std.string(size)) 49 | ) 50 | .add( 51 | new Element('family') 52 | .setAttribute('val', Std.string(family)) 53 | ); 54 | 55 | // xml.add( 56 | // new Element('name') 57 | // .setAttribute('val', name) 58 | // ); 59 | 60 | return xml; 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /src/openxml/util/XmlTools.hx: -------------------------------------------------------------------------------- 1 | package openxml.util; 2 | import archive.Entry; 3 | using haxe.xml.Printer; 4 | using openxml.util.XmlTools; 5 | 6 | using tink.CoreApi; 7 | 8 | /** 9 | * ... 10 | * @author Kevin 11 | */ 12 | class XmlTools 13 | { 14 | 15 | public static function addElement(xml:Xml, name:String, ?text:String, ?attr:Dynamic):Xml 16 | { 17 | var e = Xml.createElement(name); 18 | xml.addChild(e); 19 | 20 | if (text != null && text != "") 21 | e.setInnerText(text); 22 | 23 | if (attr != null) 24 | { 25 | for (a in Reflect.fields(attr)) 26 | xml.setAttr(a, Reflect.field(attr, a)); 27 | } 28 | 29 | return e; 30 | } 31 | 32 | public static function addProcessingInstruction(xml:Xml, data:String):Xml 33 | { 34 | var pi = Xml.createProcessingInstruction(data); 35 | xml.addChild(pi); 36 | return pi; 37 | } 38 | 39 | public static inline function firstElementNamed(xml:Xml, name:String):Xml 40 | { 41 | return xml.elementsNamed('name').next(); 42 | } 43 | 44 | public static inline function setInnerText(xml:Xml, text:String):Void 45 | { 46 | xml.addChild(Xml.createPCData(text)); 47 | } 48 | 49 | public static inline function setAttr(xml:Xml, name:String, value:Dynamic):Void 50 | { 51 | xml.set(name, Std.string(value)); 52 | } 53 | 54 | public static function toEntry(obj:IXml, path:String):Entry { 55 | var xml = obj.toXml().toString(); 56 | return { 57 | name: path, 58 | size: xml.length, 59 | source: xml 60 | } 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /src/openxml/spreadsheet/SharedStrings.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet; 2 | 3 | import xml.*; 4 | import openxml.util.IXml; 5 | 6 | /** 7 | * ... 8 | * @author Kevin 9 | */ 10 | class SharedStrings implements IXml { 11 | public static var instance:SharedStrings = new SharedStrings(); 12 | 13 | var strings:Array<{value:String, count:Int}>; 14 | var index:Int; 15 | 16 | function new() { 17 | strings = []; 18 | } 19 | 20 | public function addString(str:String):Int { 21 | var index = getIndex(str); 22 | 23 | if (index == -1) 24 | index = strings.push({value:str, count:1}) - 1; 25 | else 26 | strings[index].count ++; 27 | 28 | return index; 29 | } 30 | 31 | public function removeString(str:String) { 32 | var index = getIndex(str); 33 | if (index != -1) strings[index].count --; 34 | } 35 | 36 | public function getIndex(str:String):Int { 37 | for (i in 0...strings.length) if (strings[i].value == str) return i; 38 | return -1; 39 | } 40 | 41 | public function toXml():Xml { 42 | var doc = new Document( 43 | new ProcessingInstruction('xml version="1.0" encoding="UTF-8" standalone="yes"'), 44 | new Element('sst') 45 | .setAttribute('xmlns', XmlNameSpaces.spreadsheetml.MAIN) 46 | ); 47 | 48 | 49 | var count = 0; 50 | for (s in strings) { 51 | count += s.count; 52 | doc.root.add( 53 | new Element('si') 54 | .add(new Element('t').addText(s.value)) 55 | ); 56 | } 57 | 58 | doc.root 59 | .setAttribute('count', count) 60 | .setAttribute('uniqueCount', strings.length); 61 | 62 | return doc.toXml(); 63 | } 64 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##### Alpha: This is an alpha version. Expect drastic API changes in the future. 2 | 3 | 4 | # openxml 5 | Write OpenXML (xlsx, docx, pptx) files with Haxe 6 | 7 | This is a library I wrote for my own use at work. So it will include only the features I need. In other words, do not expect the whole Open XML spec to be implemented. However, feel free to raise issues or feature requests and I will try to fix/add accordingly. Pull requests are highly appreciated. 8 | 9 | #### Spreadsheet 10 | 11 | Allows writing a .xlsx file. 12 | 13 | Supports worksheets, cells, cell contents (partial), cell styles (partial) 14 | 15 | **Supported cell contents:** 16 | 17 | - Boolean 18 | - Text 19 | - Number 20 | - Formula 21 | 22 | **Supported cell styles (formatting):** 23 | 24 | - Font (font family, font name, font size, bold, italic) 25 | - Pattern Fill & Solid Fill 26 | 27 | #### Word Processcing 28 | 29 | Allows writing a .docx file 30 | 31 | Only simple texts are supported at the moment. 32 | 33 | ### Install 34 | `haxelib git openxml https://github.com/kevinresol/openxml` 35 | 36 | ### Usage 37 | Check out the code samples in the "test" directory. 38 | 39 | ### OpenXML Specs 40 | 41 | http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-376,%20Fourth%20Edition,%20Part%201%20-%20Fundamentals%20And%20Markup%20Language%20Reference.zip 42 | 43 | 44 | ### Running the tests 45 | 46 | Copy `System.Xml.dll` and `System.Xml.Linq.dll` from .NET 4.0 to `/netlib/net-40` 47 | Then run the following: 48 | ``` 49 | haxe validator.hxml 50 | haxelib install travix 51 | haxelib run travix install 52 | haxelib run travix neko 53 | ``` -------------------------------------------------------------------------------- /src/openxml/spreadsheet/Workbook.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet; 2 | 3 | import xml.*; 4 | import openxml.spreadsheet.style.Styles; 5 | import openxml.util.IXml; 6 | /** 7 | * ... 8 | * @author Kevin 9 | */ 10 | class Workbook implements IXml { 11 | public var worksheets:Array; 12 | public var relationships:Relationships; 13 | public var styles:Styles; 14 | 15 | public function new() { 16 | worksheets = []; 17 | relationships = new Relationships(); 18 | styles = new Styles(); 19 | } 20 | 21 | public function addWorksheet(name:String):Worksheet { 22 | var ws = new Worksheet(this, name); 23 | worksheets.push(ws); 24 | ws.id = worksheets.length; 25 | relationships.add(RTWorksheet, 'worksheets/sheet${ws.id}.xml'); 26 | return ws; 27 | } 28 | 29 | public function getWorksheet(name:String):Worksheet { 30 | for (ws in worksheets) if (ws.name == name) return ws; 31 | return null; 32 | } 33 | 34 | public function toXml() { 35 | var doc = new Document( 36 | new ProcessingInstruction('xml version="1.0" encoding="UTF-8" standalone="yes"'), 37 | new Element('workbook') 38 | .setAttribute('xmlns', XmlNameSpaces.spreadsheetml.MAIN) 39 | .setAttribute('xmlns:r', XmlNameSpaces.officeDocument.RELATIONSHIPS) 40 | ); 41 | 42 | 43 | var sheets = new Element('sheets'); 44 | doc.root.add(sheets); 45 | 46 | for (i in 0...worksheets.length) { 47 | var ws = worksheets[i]; 48 | var id = i + 1; 49 | sheets.add( 50 | new Element('sheet') 51 | .setAttribute('name', ws.name) 52 | .setAttribute('sheetId', '$id') 53 | .setAttribute('r:id', 'rId$id') 54 | ); 55 | } 56 | 57 | return doc.toXml(); 58 | } 59 | } -------------------------------------------------------------------------------- /src/openxml/Relationships.hx: -------------------------------------------------------------------------------- 1 | package openxml; 2 | 3 | import xml.*; 4 | import openxml.util.IXml; 5 | 6 | /** 7 | * ... 8 | * @author Kevin 9 | */ 10 | class Relationships extends Document implements IXml { 11 | var counter = 1; 12 | 13 | public function add(type:RelationshipType, target:String) { 14 | root.add( 15 | new Element('Relationship') 16 | .setAttribute('Id', 'rId${counter++}') 17 | .setAttribute('Type', type) 18 | .setAttribute('Target', target) 19 | ); 20 | } 21 | 22 | public function new() { 23 | super( 24 | new ProcessingInstruction('xml version="1.0" encoding="UTF-8"'), 25 | new Element('Relationships') 26 | .setAttribute('xmlns', XmlNameSpaces.pack.RELATIONSHIPS) 27 | ); 28 | } 29 | } 30 | 31 | @:enum 32 | abstract RelationshipType(String) to String to AttributeValue { 33 | // common 34 | var RTCoreProperties = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; 35 | 36 | var RTExtendedProperties = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; 37 | var RTOfficeDocument = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; 38 | 39 | // spreadsheet 40 | var RTWorksheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"; 41 | var RTSharedStrings = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"; 42 | var RTStyles = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; 43 | 44 | // wordprocessing 45 | 46 | } 47 | 48 | typedef Relationship = { 49 | object:IXml, 50 | type:RelationshipType, 51 | target:String, 52 | } -------------------------------------------------------------------------------- /src/openxml/wordprocessing/Writer.hx: -------------------------------------------------------------------------------- 1 | package openxml.wordprocessing; 2 | 3 | import archive.zip.Zip; 4 | import openxml.ContentTypes; 5 | import openxml.CoreProperties; 6 | import openxml.ExtendedProperties; 7 | import openxml.Relationships; 8 | import openxml.util.IXml; 9 | import tink.streams.Stream; 10 | 11 | using openxml.util.XmlTools; 12 | using tink.io.Source; 13 | using tink.CoreApi; 14 | /** 15 | * ... 16 | * @author Kevin 17 | */ 18 | class Writer { 19 | var zip:Zip; 20 | 21 | public function new(zip) { 22 | this.zip = zip; 23 | } 24 | 25 | public function write(document:Document) { 26 | 27 | var entries = []; 28 | var core = new CoreProperties(); 29 | var app = new ExtendedProperties(AppWord); 30 | var contentTypes = new ContentTypes(); 31 | var relationships = new Relationships(); 32 | 33 | contentTypes.addPart("/docProps/core.xml", CTCoreProperties); 34 | contentTypes.addPart("/docProps/app.xml", CTExtendedProperties); 35 | contentTypes.addPart('/word/document.xml', CTDocument); 36 | 37 | relationships.add(RTExtendedProperties, "docProps/app.xml"); 38 | relationships.add(RTCoreProperties, "docProps/core.xml"); 39 | relationships.add(RTOfficeDocument, "word/document.xml"); 40 | 41 | entries.push(relationships.toEntry('_rels/.rels')); 42 | entries.push(contentTypes.toEntry('[Content_Types].xml')); 43 | entries.push(core.toEntry('docProps/core.xml')); 44 | entries.push(app.toEntry('docProps/app.xml')); 45 | entries.push(document.toEntry('word/document.xml')); 46 | entries.push(document.relationships.toEntry('word/_rels/document.xml.rels')); 47 | 48 | 49 | return zip.pack(Stream.ofIterator(entries.iterator())); 50 | } 51 | 52 | 53 | } -------------------------------------------------------------------------------- /tests/TestSpreadsheet.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import openxml.spreadsheet.style.Font; 4 | import openxml.spreadsheet.Workbook; 5 | import openxml.spreadsheet.Writer; 6 | 7 | @:asserts 8 | class TestSpreadsheet { 9 | public function new() {} 10 | 11 | public function testOutput() { 12 | var wb = new Workbook(); 13 | var ws = wb.addWorksheet('SheetA'); 14 | ws.getCell(1, 1).content = CString("A string value"); 15 | ws.getCell(1, 2).content = CString("Same string value"); 16 | ws.getCell(3, 3).content = CString("Same string value"); 17 | ws.getCell(4, 4).content = CFormula("A1+A2"); 18 | ws.getCell(4, 5).content = CNumber(1.262234936); 19 | 20 | var ws = wb.addWorksheet('SheetB'); 21 | 22 | var cell = ws.getCell(3, 3); 23 | cell.content = CString("Same string value"); 24 | cell.clearContent(); 25 | 26 | var cell = ws.getCell(4, 4); 27 | cell.content = CFormula("A1+A2"); 28 | var font = wb.styles.fonts.addFont(); 29 | font.size = 50; 30 | cell.format.font = font; 31 | 32 | var fill = wb.styles.fills.addFill(); 33 | fill.patternFill.type = PFDarkGray; 34 | cell.format.fill = fill; 35 | 36 | ws.getCell(4, 5).content = CNumber(1.262234936); 37 | var fill = wb.styles.fills.addFill(); 38 | fill.patternFill.type = PFSolid(0xffff0000); 39 | ws.getCell(4, 5).format.fill = fill; 40 | 41 | 42 | var w = new Writer(new archive.zip.NodeZip()); 43 | var path = 'bin/output.xlsx'; 44 | w.write(wb).pipeTo(tink.io.Sink.ofNodeStream('name', js.node.Fs.createWriteStream(path))) 45 | .handle(function(o) { 46 | asserts.assert(RunTests.runValidator('spreadsheet', path) == 0); 47 | asserts.done(); 48 | }); 49 | 50 | return asserts; 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | 4 | language: node_js 5 | node_js: 6 6 | 7 | os: 8 | - linux 9 | # - osx 10 | 11 | haxe: 12 | - "3.2.1" 13 | - development 14 | 15 | matrix: 16 | allow_failures: 17 | - haxe: development 18 | 19 | install: 20 | - wget -q -O - http://archive.getdeb.net/getdeb-archive.key | sudo apt-key add - 21 | - sudo sh -c 'echo "deb http://archive.getdeb.net/ubuntu trusty-getdeb games" >> /etc/apt/sources.list.d/getdeb.list' 22 | - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF 23 | - echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list 24 | - sudo apt-get update 25 | - sudo apt-get install -y nuget mono-complete 26 | # - sudo mozroots --import --machine --sync 27 | - yes | sudo certmgr -ssl -m https://go.microsoft.com 28 | - yes | sudo certmgr -ssl -m https://nugetgallery.blob.core.windows.net 29 | - yes | sudo certmgr -ssl -m https://nuget.org 30 | - yarn 31 | - haxelib install hxcs 32 | 33 | before_script: 34 | - export HXCS_PATH=$(haxelib path hxcs | head -n 1) 35 | - cp lib/System.Xml.Linq.dll $HXCS_PATH/netlib/net-40/ 36 | - cp lib/System.Xml.dll $HXCS_PATH/netlib/net-40/ 37 | - cd sdk && ./build.open-xml-sdk.sh || true && cd .. 38 | - yarn run haxe validator.hxml 39 | 40 | script: 41 | # - haxelib run travix interp 42 | # - haxelib run travix neko 43 | # - haxelib run travix python 44 | - yarn run travix node 45 | # - haxelib run travix js 46 | # - haxelib run travix flash 47 | # - haxelib run travix java 48 | # - haxelib run travix cpp 49 | # - haxelib run travix cs 50 | # - haxelib run travix php 51 | -------------------------------------------------------------------------------- /test/Spreadsheet.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import openxml.spreadsheet.style.Font; 4 | import openxml.spreadsheet.Workbook; 5 | import openxml.spreadsheet.Writer; 6 | import sys.io.File; 7 | 8 | /** 9 | * ... 10 | * @author Kevin 11 | */ 12 | 13 | class Spreadsheet 14 | { 15 | 16 | static function main() 17 | { 18 | var wb = new Workbook(); 19 | var ws = wb.addWorksheet('SheetA'); 20 | ws.getCell(1, 1).content = CString("A string value"); 21 | ws.getCell(1, 2).content = CString("Same string value"); 22 | ws.getCell(3, 3).content = CString("Same string value"); 23 | ws.getCell(4, 4).content = CFormula("A1+A2"); 24 | ws.getCell(4, 5).content = CNumber(1.262234936); 25 | 26 | var ws = wb.addWorksheet('SheetB'); 27 | 28 | var cell = ws.getCell(3, 3); 29 | cell.content = CString("Same string value"); 30 | cell.clearContent(); 31 | 32 | var cell = ws.getCell(4, 4); 33 | cell.content = CFormula("A1+A2"); 34 | var font = wb.styles.fonts.addFont(); 35 | font.size = 50; 36 | cell.format.font = font; 37 | 38 | var fill = wb.styles.fills.addFill(); 39 | fill.patternFill.type = PFDarkGray; 40 | cell.format.fill = fill; 41 | 42 | ws.getCell(4, 5).content = CNumber(1.262234936); 43 | var fill = wb.styles.fills.addFill(); 44 | fill.patternFill.type = PFSolid(0xffff0000); 45 | ws.getCell(4, 5).format.fill = fill; 46 | 47 | var w = new Writer(new archive.zip.NodeZip()); 48 | w.write(wb).pipeTo(tink.io.Sink.ofNodeStream('name', js.node.Fs.createWriteStream('output.xlsx'))) 49 | .handle(function(o) { 50 | trace(o); 51 | Sys.exit(0); 52 | }); 53 | 54 | // var f = File.write('output.xlsx', true); 55 | // var w = new Writer(f); 56 | // w.write(wb); 57 | // f.close(); 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /src/openxml/ExtendedProperties.hx: -------------------------------------------------------------------------------- 1 | package openxml; 2 | 3 | import xml.*; 4 | import openxml.util.IXml; 5 | 6 | /** 7 | * ... 8 | * @author Kevin 9 | */ 10 | class ExtendedProperties extends Document implements IXml { 11 | public function new(application:Application) { 12 | super( 13 | new ProcessingInstruction('xml version="1.0" encoding="UTF-8"'), 14 | new Element('Properties') 15 | .setAttribute('xmlns', "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties") 16 | .setAttribute('xmlns:vt', "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes") 17 | .add(new Element('Application').addText(application)) 18 | .add(new Element('DocSecurity').addText('0')) 19 | .add(new Element('ScaleCrop').addText('false')) 20 | ); 21 | } 22 | } 23 | 24 | @:enum 25 | abstract Application(String) to String { 26 | var AppExcel = 'Microsoft Excel'; 27 | var AppWord = 'Microsoft Office Word'; 28 | } 29 | 30 | /* 31 | Microsoft Excel 32 | 0 33 | false 34 | 35 | 36 | 37 | Worksheets 38 | 39 | 40 | 1 41 | 42 | 43 | 44 | 45 | 46 | Sheet1 47 | 48 | 49 | false 50 | false 51 | false 52 | 12.0000 53 | */ -------------------------------------------------------------------------------- /src/openxml/spreadsheet/style/Styles.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet.style; 2 | 3 | import xml.*; 4 | import openxml.spreadsheet.style.Border.Borders; 5 | import openxml.spreadsheet.style.Fill.Fills; 6 | import openxml.spreadsheet.style.Font.Fonts; 7 | import openxml.spreadsheet.style.Format.CellFormats; 8 | import openxml.spreadsheet.style.Format.FormattingRecords; 9 | import openxml.spreadsheet.style.NumberFormat.NumberFormats; 10 | import openxml.util.IXml; 11 | /** 12 | * ... 13 | * @author ... 14 | */ 15 | @:allow(openxml.spreadsheet) 16 | class Styles implements IXml { 17 | public var fonts:Fonts; 18 | public var fills:Fills; 19 | public var borders:Borders; 20 | public var numberFormats:NumberFormats; 21 | 22 | var formattingRecords:FormattingRecords; 23 | var cellFormats:CellFormats; 24 | 25 | public function new() { 26 | fonts = new Fonts(); 27 | fills = new Fills(); 28 | borders = new Borders(); 29 | numberFormats = new NumberFormats(); 30 | 31 | formattingRecords = new FormattingRecords(this); 32 | cellFormats = new CellFormats(this); 33 | } 34 | 35 | public function toXml():Xml { 36 | var doc = new Document( 37 | new ProcessingInstruction('xml version="1.0" encoding="UTF-8" standalone="yes"'), 38 | new Element('styleSheet') 39 | .setAttribute('xmlns', XmlNameSpaces.spreadsheetml.MAIN) 40 | .add(fonts.toXml()) 41 | .add(fills.toXml()) 42 | .add(borders.toXml()) 43 | //.add(numberFormats.toXml()) 44 | .add(formattingRecords.toXml()) 45 | .add(cellFormats.toXml()) 46 | ); 47 | return doc.toXml(); 48 | 49 | } 50 | } 51 | 52 | /*class Style implements IXml 53 | { 54 | var styleTypes:Array; 55 | 56 | public function new() 57 | { 58 | styleTypes = []; 59 | } 60 | 61 | public function toXml():Xml 62 | { 63 | 64 | } 65 | }*/ 66 | 67 | -------------------------------------------------------------------------------- /src/openxml/spreadsheet/Worksheet.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet; 2 | 3 | import xml.*; 4 | import openxml.spreadsheet.Cell.A1Reference; 5 | import openxml.util.IXml; 6 | import openxml.XmlNameSpaces; 7 | 8 | 9 | /** 10 | * ... 11 | * @author Kevin 12 | */ 13 | class Worksheet implements IXml { 14 | public var parent(default, null):Workbook; 15 | public var name:String; 16 | public var id:Int; 17 | 18 | var cells:Map; 19 | 20 | public function new(workbook:Workbook, name:String) { 21 | parent = workbook; 22 | this.name = name; 23 | cells = new Map(); 24 | } 25 | 26 | public function toXml():Xml { 27 | var doc = new Document( 28 | new ProcessingInstruction('xml version="1.0" encoding="UTF-8" standalone="yes"'), 29 | new Element('worksheet') 30 | .setAttribute('xmlns', XmlNameSpaces.spreadsheetml.MAIN) 31 | .setAttribute('xmlns:r', XmlNameSpaces.officeDocument.RELATIONSHIPS) 32 | ); 33 | var minRow = 1000000; 34 | var maxRow = 0; 35 | var minCol = 65536; 36 | var maxCol = 0; 37 | 38 | var rows:Array = []; 39 | 40 | for (cell in cells) { 41 | var row = rows.filter(function(r) return r.row == cell.row)[0]; 42 | if (row == null) 43 | rows.push(row = new Row(cell.row)); 44 | 45 | if (cell.row < minRow) minRow = cell.row; 46 | if (cell.col < minCol) minCol = cell.col; 47 | if (cell.row > maxRow) maxRow = cell.row; 48 | if (cell.col > maxCol) maxCol = cell.col; 49 | 50 | row.addCell(cell); 51 | } 52 | 53 | doc.root.add( 54 | new Element('dimension') 55 | .setAttribute('ref', A1Reference.createRange(minRow, minCol, maxRow, maxCol)) 56 | ); 57 | 58 | var sheetData = new Element('sheetData'); 59 | doc.root.add(sheetData); 60 | 61 | rows.sort(function(r1, r2) return r1.row - r2.row); 62 | for (row in rows) sheetData.add(row.toXml()); 63 | 64 | return doc.toXml(); 65 | } 66 | 67 | public function getCell(row:Int, col:Int):Cell { 68 | var a1ref = A1Reference.create(row, col); 69 | if (!cells.exists(a1ref)) 70 | cells[a1ref] = new Cell(this, row, col); 71 | 72 | return cells[a1ref]; 73 | } 74 | } -------------------------------------------------------------------------------- /tests/Validator.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import documentformat.openxml.packaging.*; 4 | import documentformat.openxml.validation.*; 5 | import documentformat.openxml.wordprocessing.*; 6 | 7 | class Validator { 8 | static function main() { 9 | trace('Starting Validator'); 10 | var args = Sys.args(); 11 | var type = args[0]; 12 | var path = args[1]; 13 | 14 | var isValid = switch type { 15 | case 'wordprocessing': validateWordprocessing(path); 16 | case 'spreadsheet': validateSpreadsheet(path); 17 | default: false; 18 | } 19 | 20 | Sys.exit(isValid ? 0 : 500); 21 | } 22 | static function validateWordprocessing(path:String) { 23 | trace('Validating Wordprocessing: $path'); 24 | var doc = WordprocessingDocument.Open(path, false); 25 | var validator = new OpenXmlValidator(); 26 | var errors = validator.Validate(doc); 27 | 28 | var hasError = false; 29 | var enumerator = errors.GetEnumerator(); 30 | while(enumerator.MoveNext()) { 31 | if(!hasError) { 32 | hasError = true; 33 | trace('Document is invalid'); 34 | } 35 | var error = enumerator.Current; 36 | trace('Error description: ' + error.Description); 37 | trace('Content type of part with error: ' + error.Part.ContentType); 38 | trace('Location of error: ' + error.Path.XPath); 39 | } 40 | if(!hasError) trace('Document is valid'); 41 | return !hasError; 42 | } 43 | static function validateSpreadsheet(path:String) { 44 | trace('Validating Spreadsheet: $path'); 45 | var doc = SpreadsheetDocument.Open(path, false); 46 | var validator = new OpenXmlValidator(); 47 | var errors = validator.Validate(doc); 48 | 49 | var hasError = false; 50 | var enumerator = errors.GetEnumerator(); 51 | while(enumerator.MoveNext()) { 52 | if(!hasError) { 53 | hasError = true; 54 | trace('Spreadsheet is invalid'); 55 | } 56 | var error = enumerator.Current; 57 | trace('Error description: ' + error.Description); 58 | trace('Content type of part with error: ' + error.Part.ContentType); 59 | trace('Location of error: ' + error.Path.XPath); 60 | } 61 | if(!hasError) trace('Spreadsheet is valid'); 62 | return !hasError; 63 | } 64 | } -------------------------------------------------------------------------------- /src/openxml/ContentTypes.hx: -------------------------------------------------------------------------------- 1 | package openxml; 2 | 3 | import xml.*; 4 | import openxml.util.IXml; 5 | 6 | /** 7 | * ... 8 | * @author Kevin 9 | */ 10 | class ContentTypes extends Document implements IXml { 11 | 12 | public function new() { 13 | super( 14 | new ProcessingInstruction('xml version="1.0" encoding="UTF-8" standalone="yes"'), 15 | new Element('Types') 16 | .setAttribute('xmlns', XmlNameSpaces.pack.CONTENT_TYPES) 17 | .setAttribute('xmlns:xsd', "http://www.w3.org/2001/XMLSchema") 18 | .setAttribute('xmlns:xsi', "http://www.w3.org/2001/XMLSchema-instance") 19 | .add( 20 | new Element('Default') 21 | .setAttribute('Extension', 'rels') 22 | .setAttribute('ContentType', CTRelationships) 23 | ) 24 | .add( 25 | new Element('Default') 26 | .setAttribute('Extension', 'xml') 27 | .setAttribute('ContentType', CTXml) 28 | ) 29 | ); 30 | } 31 | 32 | public function addPart(partName:String, contentType:ContentType) { 33 | root.add( 34 | new Element('Override') 35 | .setAttribute('PartName', partName) 36 | .setAttribute('ContentType', contentType) 37 | ); 38 | } 39 | } 40 | 41 | @:enum 42 | abstract ContentType(String) to String to AttributeValue { 43 | var CTXml = "application/xml"; 44 | 45 | var CTRelationships = "application/vnd.openxmlformats-package.relationships+xml"; 46 | var CTCoreProperties = "application/vnd.openxmlformats-package.core-properties+xml"; 47 | 48 | var CTExtendedProperties = "application/vnd.openxmlformats-officedocument.extended-properties+xml"; 49 | var CTTheme = "application/vnd.openxmlformats-officedocument.theme+xml"; 50 | 51 | var CTWorkbook = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"; 52 | var CTWorksheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"; 53 | var CTSharedStrings = "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"; 54 | var CTStyles = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"; 55 | 56 | var CTDocument = "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"; 57 | 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/openxml/wordprocessing/Document.hx: -------------------------------------------------------------------------------- 1 | package openxml.wordprocessing; 2 | 3 | import openxml.Relationships; 4 | import openxml.util.IXml; 5 | using openxml.util.XmlTools; 6 | /** 7 | * ... 8 | * @author ... 9 | */ 10 | class Document implements IXml 11 | { 12 | public var body:Body; 13 | public var relationships:Relationships; 14 | 15 | public function new() 16 | { 17 | body = new Body(); 18 | relationships = new Relationships(); 19 | } 20 | 21 | public function toXml():Xml 22 | { 23 | var xml = Xml.createDocument(); 24 | xml.addProcessingInstruction('xml version="1.0" encoding="UTF-8" standalone="yes"'); 25 | 26 | var xdoc = xml.addElement('w:document'); 27 | 28 | xdoc.set('xmlns:r', XmlNameSpaces.officeDocument.RELATIONSHIPS); 29 | xdoc.set('xmlns:w', XmlNameSpaces.wordprocessingml.MAIN); 30 | /* 31 | xmlns:wp = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" 32 | xmlns:m = "http://schemas.openxmlformats.org/officeDocument/2006/math" 33 | xmlns:ve = "http://schemas.openxmlformats.org/markup-compatibility/2006" 34 | 35 | xmlns:w10 = "urn:schemas-microsoft-com:office:word" 36 | xmlns:v = "urn:schemas-microsoft-com:vml" 37 | xmlns:o = "urn:schemas-microsoft-com:office:office" 38 | */ 39 | xdoc.addChild(body.toXml()); 40 | 41 | return xml; 42 | } 43 | 44 | } 45 | 46 | class Body implements IXml 47 | { 48 | var paragraphs:Array; 49 | 50 | public function new() 51 | { 52 | paragraphs = []; 53 | } 54 | 55 | public function addParagraph(?text:String):Paragraph 56 | { 57 | var p = new Paragraph(text); 58 | paragraphs.push(p); 59 | return p; 60 | } 61 | 62 | public function toXml():Xml 63 | { 64 | var xml = Xml.createElement('w:body'); 65 | 66 | for (p in paragraphs) 67 | xml.addChild(p.toXml()); 68 | 69 | return xml; 70 | } 71 | } 72 | 73 | class Paragraph implements IXml 74 | { 75 | public var text:String; 76 | 77 | public function new(?text:String) 78 | { 79 | this.text = text; 80 | } 81 | 82 | public function toXml():Xml 83 | { 84 | var xml = Xml.createElement('w:p'); 85 | 86 | if (text == null) text = ''; 87 | 88 | var xr = xml.addElement('w:r'); 89 | xr.addElement('w:t', text); 90 | 91 | return xml; 92 | } 93 | } -------------------------------------------------------------------------------- /src/openxml/spreadsheet/Writer.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet; 2 | 3 | import archive.*; 4 | import archive.zip.*; 5 | import openxml.ContentTypes; 6 | import openxml.CoreProperties; 7 | import openxml.ExtendedProperties; 8 | import openxml.Relationships; 9 | import openxml.util.IXml; 10 | import tink.streams.Stream; 11 | 12 | using openxml.util.XmlTools; 13 | using tink.io.Source; 14 | using tink.CoreApi; 15 | 16 | /** 17 | * ... 18 | * @author Kevin 19 | */ 20 | class Writer { 21 | var zip:Zip; 22 | 23 | public function new(zip) { 24 | this.zip = zip; 25 | } 26 | 27 | public function write(workbook:Workbook):RealSource { 28 | var entries = []; 29 | var core = new CoreProperties(); 30 | var app = new ExtendedProperties(AppExcel); 31 | var contentTypes = new ContentTypes(); 32 | var relationships = new Relationships(); 33 | 34 | contentTypes.addPart("/docProps/core.xml", CTCoreProperties); 35 | contentTypes.addPart("/docProps/app.xml", CTExtendedProperties); 36 | contentTypes.addPart('/xl/workbook.xml', CTWorkbook); 37 | contentTypes.addPart('/xl/sharedStrings.xml', CTSharedStrings); 38 | contentTypes.addPart('/xl/styles.xml', CTStyles); 39 | 40 | for (ws in workbook.worksheets) { 41 | entries.push(ws.toEntry('xl/worksheets/sheet${ws.id}.xml')); 42 | contentTypes.addPart('/xl/worksheets/sheet${ws.id}.xml', CTWorksheet); 43 | } 44 | 45 | relationships.add(RTExtendedProperties, "docProps/app.xml"); 46 | relationships.add(RTCoreProperties, "docProps/core.xml"); 47 | relationships.add(RTOfficeDocument, "xl/workbook.xml"); 48 | 49 | workbook.relationships.add(RTSharedStrings, "sharedStrings.xml"); 50 | workbook.relationships.add(RTStyles, "styles.xml"); 51 | 52 | entries.push(relationships.toEntry('_rels/.rels')); 53 | entries.push(contentTypes.toEntry('[Content_Types].xml')); 54 | entries.push(core.toEntry('docProps/core.xml')); 55 | entries.push(app.toEntry('docProps/app.xml')); 56 | entries.push(workbook.toEntry('xl/workbook.xml')); 57 | entries.push(workbook.styles.toEntry('xl/styles.xml')); 58 | entries.push(workbook.relationships.toEntry('xl/_rels/workbook.xml.rels')); 59 | entries.push(SharedStrings.instance.toEntry('xl/sharedStrings.xml')); 60 | 61 | return zip.pack(Stream.ofIterator(entries.iterator())); 62 | // zipWriter.write(entries); 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /src/openxml/spreadsheet/style/Format.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet.style; 2 | 3 | import xml.*; 4 | import haxe.CallStack; 5 | import openxml.util.IXml; 6 | import openxml.util.XmlArray; 7 | 8 | /** 9 | * ... 10 | * @author ... 11 | */ 12 | class Formats extends XmlArray { 13 | var parent:Styles; 14 | 15 | public function new(parent:Styles, elementName:String) { 16 | super(elementName); 17 | this.parent = parent; 18 | } 19 | 20 | public function addFormat():Format { 21 | var format = new Format(); 22 | push(format); 23 | return format; 24 | } 25 | } 26 | 27 | class FormattingRecords extends Formats { 28 | public var defaultFormat(default, null):Format; 29 | 30 | public function new(styles:Styles) { 31 | super(styles, 'cellStyleXfs'); 32 | 33 | defaultFormat = new Format(); 34 | push(defaultFormat); 35 | } 36 | } 37 | 38 | class CellFormats extends Formats { 39 | public var defaultCellFormat(default, null):CellFormat; 40 | 41 | public function new(styles:Styles) { 42 | super(styles, 'cellXfs'); 43 | defaultCellFormat = cast addFormat(); 44 | } 45 | 46 | override public function addFormat():Format { 47 | var format = new CellFormat(); 48 | format.format = parent.formattingRecords.defaultFormat; 49 | push(format); 50 | return format; 51 | } 52 | } 53 | 54 | class Format implements IXml implements IXmlArrayItem { 55 | public var applyAlignment:Bool; 56 | public var applyBorder:Bool; 57 | public var applyFill:Bool; 58 | public var applyFont:Bool; 59 | public var applyNumberFormat:Bool; 60 | public var applyProtection:Bool; 61 | 62 | public var font:Font; 63 | public var border:Border; 64 | public var fill:Fill; 65 | public var numberFormat:NumberFormat; 66 | 67 | public var pivotButton:Bool; 68 | public var quotePrefix:Bool; 69 | 70 | public var id:Int; 71 | 72 | public function new() { 73 | 74 | } 75 | 76 | public function toXml():Xml { 77 | return new Element('xf') 78 | .setAttribute('borderId', border == null ? 0 : border.id) 79 | .setAttribute('fillId', fill == null ? 0 : fill.id) 80 | .setAttribute('fontId', font == null ? 0 : font.id) 81 | .setAttribute('numFmtId', numberFormat == null ? 0 : numberFormat.id); 82 | } 83 | } 84 | 85 | class CellFormat extends Format { 86 | public var format:Format; 87 | 88 | override public function toXml():Xml { 89 | var xml:Element = cast super.toXml(); 90 | if(border != null) xml.setAttribute('applyBorder', '1'); 91 | if(fill != null) xml.setAttribute('applyFill', '1'); 92 | if(font != null) xml.setAttribute('applyFont', '1'); 93 | if(numberFormat != null) xml.setAttribute('applyNumberFormat', '1'); 94 | 95 | xml.setAttribute('xfId', format.id); 96 | 97 | return xml; 98 | } 99 | } -------------------------------------------------------------------------------- /src/openxml/spreadsheet/Cell.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet; 2 | 3 | import xml.*; 4 | import openxml.spreadsheet.style.Format.CellFormat; 5 | import openxml.util.IXml; 6 | 7 | /** 8 | * ... 9 | * @author Kevin 10 | */ 11 | class Cell implements IXml { 12 | public var parent(default, null):Worksheet; 13 | public var content:CellContent; 14 | public var row:Int; 15 | public var col:Int; 16 | public var address:A1Reference; 17 | public var dataType:DataType; 18 | public var format(get, null):CellFormat; 19 | 20 | 21 | public function new(worksheet:Worksheet, row:Int, col:Int) { 22 | parent = worksheet; 23 | this.row = row; 24 | this.col = col; 25 | address = A1Reference.create(row, col); 26 | } 27 | 28 | public function clearContent() { 29 | content = null; 30 | } 31 | 32 | public function toXml():Xml { 33 | if (content == null) return null; 34 | 35 | var c = new Element('c') 36 | .setAttribute('r', address); 37 | 38 | switch content { 39 | case CBool(value): 40 | c.setAttribute('t', DTBool) 41 | .add(new Element('v').addText(Std.string(value))); 42 | case CNumber(value): 43 | c.setAttribute('t', DTNumber) 44 | .add(new Element('v').addText(Std.string(value))); 45 | case CFormula(formula): 46 | c.setAttribute('t', DTString) 47 | .add(new Element('f').addText(Std.string(formula))); 48 | case CString(value): 49 | var index = SharedStrings.instance.addString(value); 50 | c.setAttribute('t', DTSharedString) 51 | .add(new Element('v').addText(Std.string(index))); 52 | } 53 | 54 | if (format != null) 55 | c.setAttribute('s', format.id); 56 | 57 | return c; 58 | } 59 | 60 | private inline function get_format() { 61 | if (format == null) format = cast parent.parent.styles.cellFormats.addFormat(); 62 | return format; 63 | } 64 | } 65 | 66 | abstract A1Reference(String) to String to AttributeValue { 67 | public static inline function create(row:Int, col:Int):A1Reference { 68 | var address = columnNumToLetter(col) + (row + 1); 69 | return new A1Reference(address); 70 | } 71 | 72 | public static inline function createRange(row1:Int, col1:Int, row2:Int, col2:Int):A1Reference { 73 | if (row1 == row2 && col1 == col2) return create(row1, col1); 74 | 75 | var minR = row1; 76 | var maxR = row2; 77 | var minC = col1; 78 | var maxC = col2; 79 | 80 | if (row1 > row2) { minR = row2; maxR = row1; } 81 | if (col1 > col2) { minC = col2; maxC = col1; } 82 | 83 | return new A1Reference(columnNumToLetter(minC) + (minR + 1) + ":" + columnNumToLetter(maxC) + (maxR + 1)); 84 | } 85 | 86 | inline function new(ref:String) { 87 | this = ref; 88 | } 89 | 90 | static function columnNumToLetter(col:Int):String { 91 | var d = col + 1; 92 | var name = ""; 93 | var m = 0; 94 | 95 | while (d > 0) 96 | { 97 | m = (d - 1) % 26; 98 | name = String.fromCharCode(m + 65) + name; 99 | d = Std.int((d - m) / 26); 100 | } 101 | return name; 102 | } 103 | } 104 | 105 | @:enum 106 | abstract DataType(String) to String to AttributeValue { 107 | var DTBool = 'b'; 108 | var DTError = 'e'; 109 | var DTInlineString = 'inlineStr'; 110 | var DTNumber = 'n'; 111 | var DTSharedString = 's'; // shared string 112 | var DTString = 'str'; // formula string 113 | } 114 | 115 | enum CellContent { 116 | CBool(value:Bool); 117 | CNumber(value:Float); 118 | CFormula(formula:String); 119 | CString(value:String); 120 | } -------------------------------------------------------------------------------- /src/openxml/spreadsheet/style/Fill.hx: -------------------------------------------------------------------------------- 1 | package openxml.spreadsheet.style; 2 | 3 | import xml.*; 4 | import openxml.util.Color; 5 | import openxml.util.IXml; 6 | import openxml.util.XmlArray; 7 | 8 | /** 9 | * ... 10 | * @author ... 11 | */ 12 | class Fills extends XmlArray { 13 | public function new() { 14 | super('fills'); 15 | 16 | // excel overrides the first two fill entries 17 | addFill(); 18 | addFill(); 19 | } 20 | 21 | public function addFill():Fill { 22 | var fill = new Fill(); 23 | push(fill); 24 | return fill; 25 | } 26 | 27 | } 28 | 29 | class Fill implements IXmlArrayItem { 30 | public var patternFill:PatternFill; 31 | 32 | public var id:Int; 33 | 34 | public function new() { 35 | patternFill = new PatternFill(); 36 | } 37 | 38 | public function toXml():Xml { 39 | var xfill = Xml.createElement('fill'); 40 | 41 | xfill.addChild(patternFill.toXml()); 42 | 43 | return xfill; 44 | } 45 | } 46 | 47 | class PatternFill implements IXml { 48 | public var type:PatternType = PFNone; 49 | 50 | public var foregroundColor(get, null):Color; 51 | public var backgroundColor(get, null):Color; 52 | 53 | var hasForegroundColor:Bool = false; 54 | var hasBackgroundColor:Bool = false; 55 | 56 | public function new() { 57 | 58 | } 59 | 60 | public function toXml():Xml { 61 | var xpf = new Element('patternFill'); 62 | 63 | switch type { 64 | case PFNone: xpf.setAttribute('patternType', 'none'); 65 | case PFGray0625: xpf.setAttribute('patternType', 'gray0125'); 66 | case PFGray125: xpf.setAttribute('patternType', 'gray125'); 67 | case PFMediumGray: xpf.setAttribute('patternType', 'mediumGray'); 68 | 69 | case PFDarkDown: xpf.setAttribute('patternType', 'darkDown'); 70 | case PFDarkGray: xpf.setAttribute('patternType', 'darkGray'); 71 | case PFDarkHorizontal: xpf.setAttribute('patternType', 'darkHorizontal'); 72 | case PFDarkTrellis: xpf.setAttribute('patternType', 'darkTrellis'); 73 | case PFDarkUp: xpf.setAttribute('patternType', 'darkUp'); 74 | case PFDarkVertical: xpf.setAttribute('patternType', 'darkVertical'); 75 | 76 | case PFLightDown: xpf.setAttribute('patternType', 'lightDown'); 77 | case PFLightGray: xpf.setAttribute('patternType', 'lightGray'); 78 | case PFLightHorizontal: xpf.setAttribute('patternType', 'lightHorizontal'); 79 | case PFLightTrellis : xpf.setAttribute('patternType', 'lightTrellis'); 80 | case PFLightUp: xpf.setAttribute('patternType', 'lightUp'); 81 | case PFLightVertical: xpf.setAttribute('patternType', 'lightVertical'); 82 | 83 | case PFSolid(color): 84 | xpf.setAttribute('patternType', 'solid'); 85 | foregroundColor.argb = color; 86 | } 87 | 88 | if (hasForegroundColor) xpf.add(foregroundColor.toXml()); 89 | if (hasBackgroundColor) xpf.add(backgroundColor.toXml()); 90 | 91 | return xpf; 92 | } 93 | 94 | private function get_foregroundColor():Color { 95 | if (foregroundColor == null) { 96 | foregroundColor = new Color('fgColor'); 97 | hasForegroundColor = true; 98 | } 99 | return foregroundColor; 100 | } 101 | 102 | private function get_backgroundColor():Color{ 103 | if (backgroundColor == null) { 104 | backgroundColor = new Color('bgColor'); 105 | hasBackgroundColor = true; 106 | } 107 | return backgroundColor; 108 | } 109 | } 110 | 111 | enum PatternType { 112 | PFNone; 113 | 114 | PFGray125; 115 | PFGray0625; 116 | PFMediumGray; 117 | 118 | PFSolid(color:Int); 119 | 120 | PFDarkDown; 121 | PFDarkGray; 122 | PFDarkHorizontal; 123 | PFDarkTrellis; 124 | PFDarkUp; 125 | PFDarkVertical; 126 | 127 | PFLightDown; 128 | PFLightGray; 129 | PFLightHorizontal; 130 | PFLightTrellis; 131 | PFLightUp; 132 | PFLightVertical; 133 | 134 | } -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | archiver-utils@^1.3.0: 6 | version "1.3.0" 7 | resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-1.3.0.tgz#e50b4c09c70bf3d680e32ff1b7994e9f9d895174" 8 | dependencies: 9 | glob "^7.0.0" 10 | graceful-fs "^4.1.0" 11 | lazystream "^1.0.0" 12 | lodash "^4.8.0" 13 | normalize-path "^2.0.0" 14 | readable-stream "^2.0.0" 15 | 16 | archiver@^2.1.1: 17 | version "2.1.1" 18 | resolved "https://registry.yarnpkg.com/archiver/-/archiver-2.1.1.tgz#ff662b4a78201494a3ee544d3a33fe7496509ebc" 19 | dependencies: 20 | archiver-utils "^1.3.0" 21 | async "^2.0.0" 22 | buffer-crc32 "^0.2.1" 23 | glob "^7.0.0" 24 | lodash "^4.8.0" 25 | readable-stream "^2.0.0" 26 | tar-stream "^1.5.0" 27 | zip-stream "^1.2.0" 28 | 29 | async@^2.0.0: 30 | version "2.6.0" 31 | resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" 32 | dependencies: 33 | lodash "^4.14.0" 34 | 35 | balanced-match@^1.0.0: 36 | version "1.0.0" 37 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 38 | 39 | bl@^1.0.0: 40 | version "1.2.1" 41 | resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" 42 | dependencies: 43 | readable-stream "^2.0.5" 44 | 45 | brace-expansion@^1.1.7: 46 | version "1.1.8" 47 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" 48 | dependencies: 49 | balanced-match "^1.0.0" 50 | concat-map "0.0.1" 51 | 52 | buffer-crc32@^0.2.1: 53 | version "0.2.13" 54 | resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" 55 | 56 | compress-commons@^1.2.0: 57 | version "1.2.2" 58 | resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.2.tgz#524a9f10903f3a813389b0225d27c48bb751890f" 59 | dependencies: 60 | buffer-crc32 "^0.2.1" 61 | crc32-stream "^2.0.0" 62 | normalize-path "^2.0.0" 63 | readable-stream "^2.0.0" 64 | 65 | concat-map@0.0.1: 66 | version "0.0.1" 67 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 68 | 69 | core-util-is@~1.0.0: 70 | version "1.0.2" 71 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 72 | 73 | crc32-stream@^2.0.0: 74 | version "2.0.0" 75 | resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-2.0.0.tgz#e3cdd3b4df3168dd74e3de3fbbcb7b297fe908f4" 76 | dependencies: 77 | crc "^3.4.4" 78 | readable-stream "^2.0.0" 79 | 80 | crc@^3.4.4: 81 | version "3.5.0" 82 | resolved "https://registry.yarnpkg.com/crc/-/crc-3.5.0.tgz#98b8ba7d489665ba3979f59b21381374101a1964" 83 | 84 | end-of-stream@^1.0.0: 85 | version "1.4.1" 86 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" 87 | dependencies: 88 | once "^1.4.0" 89 | 90 | fs.realpath@^1.0.0: 91 | version "1.0.0" 92 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 93 | 94 | glob@^7.0.0: 95 | version "7.1.2" 96 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 97 | dependencies: 98 | fs.realpath "^1.0.0" 99 | inflight "^1.0.4" 100 | inherits "2" 101 | minimatch "^3.0.4" 102 | once "^1.3.0" 103 | path-is-absolute "^1.0.0" 104 | 105 | graceful-fs@^4.1.0: 106 | version "4.1.11" 107 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 108 | 109 | haxe-travix@^0.10.2: 110 | version "0.10.2" 111 | resolved "https://registry.yarnpkg.com/haxe-travix/-/haxe-travix-0.10.2.tgz#22d9c774b80e12e5170130ea4b78125ba749197a" 112 | 113 | haxeshim@^0.12.2: 114 | version "0.12.2" 115 | resolved "https://registry.yarnpkg.com/haxeshim/-/haxeshim-0.12.2.tgz#f2f876ddc84c1d8650dae984d95e4eea28792f60" 116 | 117 | inflight@^1.0.4: 118 | version "1.0.6" 119 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 120 | dependencies: 121 | once "^1.3.0" 122 | wrappy "1" 123 | 124 | inherits@2, inherits@~2.0.3: 125 | version "2.0.3" 126 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 127 | 128 | isarray@~1.0.0: 129 | version "1.0.0" 130 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 131 | 132 | lazystream@^1.0.0: 133 | version "1.0.0" 134 | resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" 135 | dependencies: 136 | readable-stream "^2.0.5" 137 | 138 | lix.pm@^0.14.0: 139 | version "0.14.0" 140 | resolved "https://registry.yarnpkg.com/lix.pm/-/lix.pm-0.14.0.tgz#9e099a8452b459db0026654608a6625109b13121" 141 | 142 | lodash@^4.14.0, lodash@^4.8.0: 143 | version "4.17.4" 144 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 145 | 146 | minimatch@^3.0.4: 147 | version "3.0.4" 148 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 149 | dependencies: 150 | brace-expansion "^1.1.7" 151 | 152 | normalize-path@^2.0.0: 153 | version "2.1.1" 154 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" 155 | dependencies: 156 | remove-trailing-separator "^1.0.1" 157 | 158 | once@^1.3.0, once@^1.4.0: 159 | version "1.4.0" 160 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 161 | dependencies: 162 | wrappy "1" 163 | 164 | path-is-absolute@^1.0.0: 165 | version "1.0.1" 166 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 167 | 168 | process-nextick-args@~1.0.6: 169 | version "1.0.7" 170 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" 171 | 172 | readable-stream@^2.0.0, readable-stream@^2.0.5: 173 | version "2.3.3" 174 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" 175 | dependencies: 176 | core-util-is "~1.0.0" 177 | inherits "~2.0.3" 178 | isarray "~1.0.0" 179 | process-nextick-args "~1.0.6" 180 | safe-buffer "~5.1.1" 181 | string_decoder "~1.0.3" 182 | util-deprecate "~1.0.1" 183 | 184 | remove-trailing-separator@^1.0.1: 185 | version "1.1.0" 186 | resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" 187 | 188 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 189 | version "5.1.1" 190 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" 191 | 192 | string_decoder@~1.0.3: 193 | version "1.0.3" 194 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" 195 | dependencies: 196 | safe-buffer "~5.1.0" 197 | 198 | tar-stream@^1.5.0: 199 | version "1.5.5" 200 | resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.5.tgz#5cad84779f45c83b1f2508d96b09d88c7218af55" 201 | dependencies: 202 | bl "^1.0.0" 203 | end-of-stream "^1.0.0" 204 | readable-stream "^2.0.0" 205 | xtend "^4.0.0" 206 | 207 | util-deprecate@~1.0.1: 208 | version "1.0.2" 209 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 210 | 211 | wrappy@1: 212 | version "1.0.2" 213 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 214 | 215 | xtend@^4.0.0: 216 | version "4.0.1" 217 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" 218 | 219 | zip-stream@^1.2.0: 220 | version "1.2.0" 221 | resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04" 222 | dependencies: 223 | archiver-utils "^1.3.0" 224 | compress-commons "^1.2.0" 225 | lodash "^4.8.0" 226 | readable-stream "^2.0.0" 227 | --------------------------------------------------------------------------------