├── .dockerignore
├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── .octocov.yml
├── CHANGELOG.md
├── Dockerfile.test
├── Gemfile
├── LICENSE
├── Makefile
├── README.md
├── Rakefile
├── benchmarks
├── 1k_rows.rb
├── 20k_rows.rb
├── auto_width.rb
├── init.rb
├── memory.rb
├── profiler.rb
└── write_value.rb
├── examples
├── example.rb
├── example_align.rb
├── example_auto_width.rb
├── example_chart.rb
├── example_colors.rb
├── example_date_time.rb
├── example_filters.rb
├── example_formula.rb
├── example_hyperlink.rb
├── example_image.rb
├── example_styles.rb
└── logo.png
├── ext
└── fast_excel
│ ├── extconf.rb
│ └── text_width_ext.c
├── extconf.rb
├── fast_excel.gemspec
├── letters.html
├── lib
├── fast_excel.rb
└── fast_excel
│ ├── binding.rb
│ └── binding
│ ├── chart.rb
│ ├── format.rb
│ ├── workbook.rb
│ └── worksheet.rb
├── libxlsxwriter
├── .github
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows
│ │ ├── cmake_actions.yml
│ │ ├── code_style.yml
│ │ ├── coverity.yml
│ │ ├── make_actions.yml
│ │ ├── valgrind.yml
│ │ ├── windows_build.yml
│ │ └── zig_build.yml
├── .gitignore
├── .indent.pro
├── CMakeLists.txt
├── CONTRIBUTING.md
├── Changes.txt
├── LICENSE.txt
├── Makefile
├── Package.swift
├── Readme.md
├── build.zig
├── build.zig.zon
├── cmake
│ ├── FindMINIZIP.cmake
│ ├── FindPackage.cmake
│ └── i686-toolchain.cmake
├── cocoapods
│ ├── libxlsxwriter-umbrella.h
│ └── libxlsxwriter.modulemap
├── include
│ ├── xlsxwriter.h
│ └── xlsxwriter
│ │ ├── app.h
│ │ ├── chart.h
│ │ ├── chartsheet.h
│ │ ├── comment.h
│ │ ├── common.h
│ │ ├── content_types.h
│ │ ├── core.h
│ │ ├── custom.h
│ │ ├── drawing.h
│ │ ├── format.h
│ │ ├── hash_table.h
│ │ ├── metadata.h
│ │ ├── packager.h
│ │ ├── relationships.h
│ │ ├── shared_strings.h
│ │ ├── styles.h
│ │ ├── table.h
│ │ ├── theme.h
│ │ ├── third_party
│ │ ├── emyg_dtoa.h
│ │ ├── ioapi.h
│ │ ├── md5.h
│ │ ├── queue.h
│ │ ├── tmpfileplus.h
│ │ ├── tree.h
│ │ └── zip.h
│ │ ├── utility.h
│ │ ├── vml.h
│ │ ├── workbook.h
│ │ ├── worksheet.h
│ │ └── xmlwriter.h
├── lib
│ └── .gitignore
├── libxlsxwriter.podspec
├── src
│ ├── Makefile
│ ├── app.c
│ ├── chart.c
│ ├── chartsheet.c
│ ├── comment.c
│ ├── content_types.c
│ ├── core.c
│ ├── custom.c
│ ├── drawing.c
│ ├── format.c
│ ├── hash_table.c
│ ├── metadata.c
│ ├── packager.c
│ ├── relationships.c
│ ├── shared_strings.c
│ ├── styles.c
│ ├── table.c
│ ├── theme.c
│ ├── utility.c
│ ├── vml.c
│ ├── workbook.c
│ ├── worksheet.c
│ └── xmlwriter.c
├── third_party
│ ├── dtoa
│ │ ├── Makefile
│ │ ├── emyg_dtoa.c
│ │ └── emyg_dtoa.h
│ ├── md5
│ │ ├── Makefile
│ │ ├── md5.c
│ │ └── md5.h
│ ├── minizip
│ │ ├── Makefile
│ │ ├── Makefile.am
│ │ ├── Makefile.orig
│ │ ├── MiniZip64_Changes.txt
│ │ ├── MiniZip64_info.txt
│ │ ├── README.txt
│ │ ├── configure.ac
│ │ ├── crypt.h
│ │ ├── ioapi.c
│ │ ├── ioapi.h
│ │ ├── iowin32.c
│ │ ├── iowin32.h
│ │ ├── make_vms.com
│ │ ├── miniunz.c
│ │ ├── miniunzip.1
│ │ ├── minizip.1
│ │ ├── minizip.c
│ │ ├── minizip.pc.in
│ │ ├── mztools.c
│ │ ├── mztools.h
│ │ ├── unzip.c
│ │ ├── unzip.h
│ │ ├── zip.c
│ │ └── zip.h
│ └── tmpfileplus
│ │ ├── Makefile
│ │ ├── tmpfileplus.c
│ │ └── tmpfileplus.h
└── version.txt
├── sonar-project.properties
└── test
├── auto_width_test.rb
├── date_test.rb
├── default_format_test.rb
├── format_test.rb
├── reopen_test.rb
├── test_helper.rb
├── tmpfile_test.rb
├── validations_test.rb
└── worksheet_test.rb
/.dockerignore:
--------------------------------------------------------------------------------
1 | libxlsxwriter
2 | .git
3 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | test:
7 | strategy:
8 | fail-fast: false
9 | matrix:
10 | os: [ubuntu-latest, macos-latest, windows-latest]
11 | ruby: [2.7, 3.1, 3.3, 3.4]
12 |
13 | runs-on: ${{ matrix.os }}
14 |
15 | steps:
16 | - uses: actions/checkout@v2
17 | - uses: ruby/setup-ruby@v1
18 | with:
19 | ruby-version: ${{ matrix.ruby }}
20 |
21 | - run: bundle config set --local without 'benchmarks'
22 | - run: bundle install
23 | - run: make
24 | - run: make install
25 |
26 | - run: rake test
27 | - run: rake examples
28 | - run: gem build fast_excel.gemspec
29 |
30 | - name: Coverage Report by octocov
31 | if: ${{ matrix.os == 'ubuntu-latest' && matrix.ruby == '3.4' }}
32 | uses: k1LoW/octocov-action@v1
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .ruby-version
2 | .idea/
3 | try.c
4 | try.rb
5 | gen.rb
6 | gen_ffi.rb
7 | *.xlsx
8 | a.out
9 | .DS_Store
10 | *.gem
11 | *.cmake
12 | libxlsxwriter/CmakeFiles
13 | libxlsxwriter/CmakeCache.txt
14 | libxlsxwriter/dev
15 | libxlsxwriter/docs
16 | libxlsxwriter/examples
17 | libxlsxwriter/test
18 | ext/fast_excel/text_width_ext.o
19 | ext/fast_excel/Makefile
20 | ext/fast_excel/text_width_ext.bundle
21 | Gemfile.lock
22 | lib/libxlsxwriter.dylib
23 | coverage/
24 |
--------------------------------------------------------------------------------
/.octocov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | paths:
3 | - coverage/.resultset.json
4 | codeToTestRatio:
5 | code:
6 | - '**/*.rb'
7 | - '!test/**/*.rb'
8 | test:
9 | - 'test/**/*_test.rb'
10 | testExecutionTime:
11 | if: true
12 | diff:
13 | datastores:
14 | - artifact://${GITHUB_REPOSITORY}
15 | comment:
16 | if: is_pull_request
17 | deletePrevious: true
18 | report:
19 | if: is_default_branch
20 | datastores:
21 | - artifact://${GITHUB_REPOSITORY}
22 | timeout: 5min
23 | summary:
24 | if: true
25 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | #### Version 0.5.0 - 02 jan 2024
2 |
3 | * Support ruby 3.3
4 | * Sync latest libxlsxwriter
5 | * Add support for writing cell comments
6 | * Add more examples
7 | * Fix compilation of minizip on NixOS (Thanks to @Mange)
8 | * On close set empty columns to default width (Thanks to @steffansluis)
9 |
10 | #### Version 0.4.1 - 13 jan 2023
11 |
12 | * Support ruby 3.2
13 | * Improve library loading (Thanks to @sly7-7 and @BrianHawley)
14 | * Ensure Time.zone is not nil (Thanks to @ksuh90)
15 | * Get utc_offset from current value if possible (Thanks to @KevinSchiffmann)
16 | * Validate worksheet name using Libxlsxwriter (Thanks to @datbth)
17 | * Fix readme typo (Thanks to @sw4d)
18 |
19 | #### Version 0.4.0 - 14 feb 2021
20 |
21 | * Support ruby 3.0
22 | * Fix for ffi library loading issue on Windows
23 |
24 | #### Version 0.3.0 - 23 jul 2020
25 |
26 | * Add support for FastExcel::URL
27 | * Add support for writing boolean values
28 | * Add enable_filters!(end_col: X)
29 | * Allow to open with an empty existing file
30 | * Add missing enums to chart
31 | * Don't change sheet name from "" to nil
32 | * Support build with docker
33 | * Fix crash when sheet name exceeds maximum length.
34 | * [BREAKING CHANGE] Rename `worksheet.right_to_left` to `worksheet.set_right_to_left`:
35 | - now it will work properly when using the `pry-rails` gem, not forcing the document start from right even when this method is not called.
36 |
37 | #### Version 0.2.6 - 26 jan 2019
38 |
39 | * Add column auto width (thanks to @duffyjp)
40 |
41 | #### Version 0.2.5 - 22 jun 2018
42 |
43 | * Update libxlsxwriter to 0.7.7
44 |
45 | #### Version 0.2.4 - 13 mar 2018
46 |
47 | * Update libxlsxwriter to 0.7.6
48 | * Don’t crash process when duplicated worksheet name
49 |
50 | #### Version 0.2.3 - 27 oct 2017
51 |
52 | * Allow Date along with DateTime in write_value (thanks to @noxern)
53 |
54 | #### Version 0.2.2 - 20 sep 2017
55 |
56 | * Nice setters and getters for format.align
57 | * Add nice setters for colors and borders
58 | * Add sheet.append_row, sheet.last_row_number
59 | * Run tests in CI
60 | * Performance optimizations and type check refactoring
61 | * Add styles_example.rb
62 | * Fix assigning align from other format
63 |
64 | #### Version 0.2.1 - 20 jun 2017
65 |
66 | * Add FastExcel::Formula
67 |
68 | #### Version 0.2.0 - 24 apr 2017
69 |
70 | * Add FastExcel.date_num
71 | * Add feature to use user default font
72 | * Add benchmarks
73 |
74 | #### Version 0.1.0 - 24 feb 2017
75 |
76 | Initial
77 |
--------------------------------------------------------------------------------
/Dockerfile.test:
--------------------------------------------------------------------------------
1 | FROM ruby
2 |
3 | RUN gem install fast_excel
4 |
5 | ARG TRAVIS_COMMIT
6 | ARG TRAVIS_BRANCH
7 | ARG GIT_REPO
8 |
9 | RUN echo "source 'https://rubygems.org'" > Gemfile
10 |
11 | RUN [ -z "$TRAVIS_COMMIT" ] && \
12 | echo "gem 'fast_excel', git: 'https://github.com/Paxa/fast_excel.git'" >> Gemfile || true
13 | RUN [ -z "$TRAVIS_COMMIT" ] || \
14 | echo "gem 'fast_excel', git: 'https://github.com/${GIT_REPO}.git', branch: '$TRAVIS_BRANCH', ref: '$TRAVIS_COMMIT'" >> Gemfile
15 |
16 | RUN cat Gemfile
17 | RUN bundle
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec
4 |
5 | gem 'rake'
6 |
7 | gem 'roo'
8 | gem 'csv'
9 | gem 'bigdecimal'
10 |
11 | gem 'simplecov', require: false
12 | gem 'minitest'
13 | gem 'minitest-reporters'
14 |
15 | group :benchmarks do
16 | gem 'caxlsx', git: 'https://github.com/caxlsx/caxlsx'
17 | gem 'write_xlsx'
18 | gem 'xlsxtream'
19 | gem 'benchmark-ips'
20 | gem 'process_memory', git: 'https://github.com/paxa/process_memory', platforms: :ruby
21 | end
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Pavel Evstigneev
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 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | Q=@
2 | ifdef V
3 | Q=
4 | endif
5 |
6 | UNAME := $(shell uname)
7 |
8 | LIBXLSXWRITER_SO = libxlsxwriter.so
9 |
10 | ifeq ($(UNAME), Darwin)
11 | LIBXLSXWRITER_SO = libxlsxwriter.dylib
12 | endif
13 |
14 | # Check for MinGW/MinGW64/Cygwin environments.
15 | ifneq (,$(findstring MINGW, $(UNAME)))
16 | MING_LIKE = y
17 | endif
18 | ifneq (,$(findstring MSYS, $(UNAME)))
19 | MING_LIKE = y
20 | endif
21 | ifneq (,$(findstring CYGWIN, $(UNAME)))
22 | MING_LIKE = y
23 | endif
24 |
25 | ifdef MING_LIKE
26 | LIBXLSXWRITER_SO = libxlsxwriter.dll
27 | endif
28 |
29 | # with xcode better to use cmake
30 | UNAME_S := $(shell uname -s)
31 | ifeq ($(UNAME_S),"Darwin")
32 | USE_CMAKE := $(shell command -v cmake 2> /dev/null)
33 | endif
34 |
35 | ifndef ($(sitearchdir))
36 | sitearchdir = './lib'
37 | endif
38 |
39 | all :
40 | # @echo "Compiling ext/text_width ..."
41 | # rake compile
42 | @echo "Compiling libxlsxwriter ..."
43 | ifdef USE_CMAKE
44 | @echo "run cmake libxlsxwriter ..."
45 | cmake libxlsxwriter
46 | else
47 | $(Q)$(MAKE) -C libxlsxwriter
48 | endif
49 |
50 | clean :
51 | $(Q)$(MAKE) clean -C libxlsxwriter
52 |
53 | install :
54 | $(Q)cp libxlsxwriter/lib/$(LIBXLSXWRITER_SO) $(sitearchdir)
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ultra Fast Excel Writer for Ruby
2 |
3 | ```ruby
4 | require 'fast_excel'
5 |
6 | workbook = FastExcel.open("hello_world.xlsx", constant_memory: true)
7 | workbook.default_format.set(
8 | font_size: 0, # user's default
9 | font_family: "Arial"
10 | )
11 |
12 | worksheet = workbook.add_worksheet("Example Report")
13 |
14 | bold = workbook.bold_format
15 | worksheet.set_column(0, 0, FastExcel::DEF_COL_WIDTH, bold)
16 |
17 | price = workbook.number_format("#,##0.00")
18 | worksheet.set_column(1, 1, 20, price)
19 |
20 | date_format = workbook.number_format("[$-409]m/d/yy h:mm AM/PM;@")
21 | worksheet.set_column(2, 2, 20, date_format)
22 |
23 | worksheet.append_row(["message", "price", "date"], bold)
24 |
25 | for i in 1..1000
26 | worksheet.append_row(["Hello", (rand * 10_000_000).round(2), Time.now])
27 | end
28 |
29 | worksheet.append_row(["Sum", FastExcel::Formula.new("SUM(B2:B1001)")], bold)
30 |
31 | workbook.close
32 | ```
33 |
34 | See [more examples](https://github.com/Paxa/fast_excel/tree/master/examples)
35 |
36 | This repository and gem contain sources of [libxlsxwriter](https://github.com/jmcnamara/libxlsxwriter)
37 |
38 | ## Install
39 |
40 | ```ruby
41 | # Gemfile
42 | gem 'fast_excel'
43 | ```
44 | Or
45 | ```
46 | gem install fast_excel
47 | ```
48 |
49 |
50 |
51 | ### Create Document
52 | ```ruby
53 | workbook = FastExcel.open # creates tmp file
54 | # ...
55 | send_data(workbook.read_string, filename: "table.xlsx") # read tmp file and delete it
56 | ```
57 |
58 | Also can use `workbook.remove_tmp_folder` to delete tmp file manually
59 |
60 |
61 | **Constant memory mode**: saves each row to disk, good for really big files but can not change previous lines that already saved
62 | ```ruby
63 | workbook = FastExcel.open(constant_memory: true)
64 | ```
65 |
66 | **Save to file**
67 | ```ruby
68 | workbook = FastExcel.open("my_dinner.xlsx")
69 | ```
70 |
71 | ### Write Data
72 | FastExcel will automatically detect data type and one of `write_number` or `write_datetime` or `write_formula` or `write_string` or `write_url`
73 | ```ruby
74 | workbook = FastExcel.open
75 | worksheet = workbook.add_worksheet
76 |
77 | # write specific type value value
78 | worksheet.write_number(row = 0, col = 5, 1_234_567, format = nil)
79 |
80 | # write value with type detection
81 | worksheet.write_value(row = 0, col = 5, 1_234_567, format = nil)
82 |
83 | # write row of values. format argument can be format object or array of format objects
84 | worksheet.write_row(row = 1, ["strong", 123_456, Time.now], format = nil)
85 |
86 | # write row to the bottom
87 | worksheet.append_row(["strong", 123_456, Time.now], )
88 |
89 | # shortcut for append_row()
90 | worksheet << ["strong", 123_456, Time.now]
91 | ```
92 |
93 | **Saving dates**: excel store dates as number of days since 1st January 1900, and FastExcel will make it for you.
94 |
95 | To make saving of dates slightly faster can use `FastExcel.date_num` helper:
96 | ```ruby
97 | date_format = workbook.number_format("[$-409]m/d/yy hh:mm;@")
98 | worksheet.write_number(0, 0, FastExcel.date_num(Time.now, Time.zone.utc_offset), date_format)
99 | ```
100 |
101 | **Formulas**: special type of value in excel
102 | ```ruby
103 | worksheet << [1, 2, 3, 4]
104 | worksheet << [FastExcel::Formula.new("SUM(A1:D1)")] # A2 will be shown as 10
105 | ```
106 |
107 | **URL**: Link to website or something else
108 | ```ruby
109 | url_format = workbook.add_format(underline: :underline_single, font_color: :blue) # format is optional
110 | worksheet.append_row([
111 | FastExcel::URL.new("https://github.com/Paxa/fast_excel"),
112 | FastExcel::URL.new("postgres://localhost")
113 | ], url_format)
114 | # or
115 | worksheet.write_url(0, 2, "https://github.com/Paxa/fast_excel", url_format)
116 | ```
117 |
118 |
119 | ### Data Formatting
120 | ```ruby
121 | format = workbook.add_format(
122 | bold: true,
123 | italic: true,
124 | font_outline: true,
125 | font_shadow: true,
126 | text_wrap: true,
127 | font_strikeout: true,
128 | shrink: true,
129 | text_justlast: true,
130 | font_size: 13, # default is 11, use 0 for user's default
131 | font_name: "Arial", # default is Calibri, also accessible via font_family
132 | font_color: :orange, # can use RGB hex as "#FF0000" or 0x00FF00 or color name as symbol or string
133 | font_script: :font_subscript,
134 | rotation: 10,
135 | underline: :underline_single, # or :underline_double or :underline_single_accounting or :underline_double_accounting
136 | indent: 1,
137 | # border styles
138 | border: :border_thin,
139 | left: :medium,
140 | top: :dashed,
141 | right: :double,
142 | bottom: :hair,
143 | bottom_color: :alice_blue,
144 | top_color: "#11ABCD",
145 | # Align
146 | align: {h: :align_center, v: :align_vertical_center},
147 | num_format: "#,##0.00"
148 | )
149 | ```
150 |
151 | **Shortcuts**:
152 | ```ruby
153 | workbook.bold_format # bold text
154 | workbook.number_format("[$-409]m/d/yy h:mm AM/PM;@") # format for date
155 | ```
156 |
157 | ### Set Column Width
158 |
159 | ```ruby
160 | worksheet.set_column(start_col, end_col, width = nil, format = nil)
161 | # or
162 | worksheet.set_column_width(col, width = 60)
163 | # or
164 | worksheet.set_columns_width(start_col, end_col, width = 60)
165 | ```
166 |
167 | ### Set Row Height
168 | ```ruby
169 | worksheet.set_row(row_num = 0, height = 30, format = nil)
170 | ```
171 |
172 | ### Column Auto Width
173 |
174 | Column authwidth only works for string values, because numbers may have custom formatting
175 |
176 | Enabling column auto widths will slow down writing string values for about 15-25%
177 |
178 | ```ruby
179 | require 'fast_excel'
180 |
181 | workbook = FastExcel.open(constant_memory: true)
182 |
183 | worksheet = workbook.add_worksheet
184 | worksheet.auto_width = true
185 |
186 | worksheet.append_row(["some text", "some longer text for example"])
187 |
188 | content = workbook.read_string
189 | File.open('./some_file.xlsx', 'wb') {|f| f.write(content) }
190 | ```
191 |
192 | 
193 |
194 |
195 | ### API
196 |
197 | This gem is FFI binding for libxlsxwriter C library with some syntax sugar. All original functions is avaliable, for example:
198 |
199 | ```ruby
200 | Libxlsxwriter.worksheet_activate(worksheet) # => will call void worksheet_activate(lxw_worksheet *worksheet)
201 | # or shorter:
202 | worksheet.activate
203 | ```
204 |
205 | Full libxlsxwriter documentation: [http://libxlsxwriter.github.io/](http://libxlsxwriter.github.io/)
206 |
207 | Generated rdoc: [rubydoc.info/github/Paxa/fast_excel](https://www.rubydoc.info/github/Paxa/fast_excel)
208 |
209 | ## Benchmarks
210 |
211 | 1000 rows:
212 | ```
213 | Comparison:
214 | FastExcel: 31.7 i/s
215 | Axlsx: 8.0 i/s - 3.98x slower
216 | write_xlsx: 6.9 i/s - 4.62x slower
217 | ```
218 |
219 | 20000 rows:
220 | ```
221 | Comparison:
222 | FastExcel: 1.4 i/s
223 | Axlsx: 0.4 i/s - 3.46x slower
224 | write_xlsx: 0.1 i/s - 17.04x slower
225 | ```
226 |
227 | Max memory usage, generating 100k rows:
228 | ```
229 | FastExcel - 20 MB
230 | Axlsx - 60 MB
231 | write_xlsx - 100 MB
232 | ```
233 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | desc "Sync github.com:Paxa/libxlsxwriter to ./libxlsxwriter"
2 | task :sync do
3 | require 'fileutils'
4 | FileUtils.rm_rf("./libxlsxwriter")
5 | system("git clone --depth 10 git@github.com:Paxa/libxlsxwriter.git")
6 | Dir.chdir("./libxlsxwriter") do
7 | system("git show --pretty='format:%cd %h' --date=iso --quiet > version.txt")
8 | FileUtils.rm_rf("./.git")
9 | end
10 | end
11 |
12 | require 'rake/testtask'
13 |
14 | Rake::TestTask.new do |test|
15 | test.test_files = Dir.glob('test/**/*_test.rb')
16 | end
17 |
18 | #task :default => :test
19 |
20 | desc "Run all examples"
21 | task :examples do
22 | Dir.glob('examples/**/*.rb').each do |file|
23 | require './' + file.sub(/\.rb$/, '')
24 | end
25 | end
26 |
27 | desc "Compile libxlsxwriter shared library"
28 | task :compile do
29 | %x{
30 | cd ext/fast_excel
31 | ruby ./extconf.rb
32 | make
33 | }
34 | end
35 |
--------------------------------------------------------------------------------
/benchmarks/1k_rows.rb:
--------------------------------------------------------------------------------
1 | require_relative 'init'
2 |
3 | HEADERS = ["id", "name", "age", "date"].freeze
4 |
5 | DATA = []
6 | 1000.times do |n|
7 | DATA << [n, "String string #{n}", (n * rand * 10).round, Time.at(n * 1000 + 1492922688)]
8 | end
9 |
10 | Benchmark.ips do |x|
11 | x.config(time: 10, warmup: 40)
12 |
13 | x.report("FastExcel") do
14 | workbook = FastExcel.open(constant_memory: true)
15 | worksheet = workbook.add_worksheet("benchmark")
16 |
17 | worksheet.write_row(0, HEADERS)
18 | DATA.each do |row|
19 | worksheet.append_row(row)
20 | end
21 | workbook.read_string
22 | end
23 |
24 | x.report("Axlsx") do
25 | filename = "#{Dir.mktmpdir}/axlsx.xlsx"
26 | Axlsx::Package.new do |package|
27 | package.use_autowidth = false
28 | package.workbook.add_worksheet do |sheet|
29 | sheet.add_row(HEADERS)
30 | DATA.each do |row|
31 | sheet.add_row(row)
32 | end
33 | end
34 | package.serialize(filename)
35 | File.open(filename, 'rb', &:read)
36 | File.delete(filename)
37 | end
38 | end
39 |
40 | x.report("write_xlsx") do
41 | filename = "#{Dir.mktmpdir}/write_xlsx.xlsx"
42 | workbook = WriteXLSX.new(filename)
43 | worksheet = workbook.add_worksheet
44 | HEADERS.each_with_index do |value, i|
45 | worksheet.write(0, i, value)
46 | end
47 | DATA.each_with_index do |row, row_num|
48 | worksheet.write_number(row_num + 1, 0, row[0])
49 | worksheet.write_string(row_num + 1, 1, row[1])
50 | worksheet.write_number(row_num + 1, 2, row[2])
51 | worksheet.write_number(row_num + 1, 3, row[3])
52 | end
53 | workbook.close
54 | File.open(filename, 'rb', &:read)
55 | File.delete(filename)
56 | end
57 |
58 | x.report("xlsxtream") do
59 | filename = "#{Dir.mktmpdir}/xlsxtream.xlsx"
60 |
61 | Xlsxtream::Workbook.open(filename) do |xlsx|
62 | xlsx.write_worksheet do |sheet|
63 | sheet << HEADERS
64 | DATA.each do |row|
65 | sheet << row
66 | end
67 | end
68 | end
69 | end
70 |
71 | x.compare!
72 | end
73 |
--------------------------------------------------------------------------------
/benchmarks/20k_rows.rb:
--------------------------------------------------------------------------------
1 | require_relative 'init'
2 |
3 | HEADERS = ["id", "name", "age", "date", "random"]
4 |
5 | DATA = []
6 | 20_000.times do |n|
7 | DATA << [n, "String string #{n}" * 5, (n * rand * 10).round, Time.at(n * 1000 + 1492922688), n * 100]
8 | end
9 |
10 | Benchmark.ips do |x|
11 | x.config(time: 10, warmup: 2)
12 |
13 | x.report("FastExcel") do
14 | write_fast_excel_20k
15 | end
16 |
17 | x.report("Axlsx") do
18 | write_axlsx_20k
19 | end
20 |
21 | x.report("write_xlsx") do
22 | write_xlsx_20k
23 | end
24 |
25 | x.report("xlsxtream") do
26 | write_xlsxtream_20k
27 | end
28 |
29 | x.compare!
30 | end
31 |
--------------------------------------------------------------------------------
/benchmarks/auto_width.rb:
--------------------------------------------------------------------------------
1 | require_relative 'init'
2 |
3 | HEADERS = ["id", "name", "age", "date"]
4 |
5 | DATA = []
6 | 1000.times do |n|
7 | DATA << [n, "String string #{n}", (n * rand * 10).round, Time.at(n * 1000 + 1492922688)]
8 | end
9 |
10 | Benchmark.ips do |x|
11 | x.config(time: 10, warmup: 2)
12 |
13 | x.report("Normal") do
14 | workbook = FastExcel.open(constant_memory: true)
15 | worksheet = workbook.add_worksheet("benchmark")
16 |
17 | worksheet.write_row(0, HEADERS)
18 | DATA.each_with_index do |row, i|
19 | worksheet.write_row(i + 1, row)
20 | end
21 | workbook.read_string
22 | end
23 |
24 | x.report("With auto_width") do
25 | workbook = FastExcel.open(constant_memory: true)
26 | worksheet = workbook.add_worksheet("benchmark")
27 | worksheet.auto_width = true
28 |
29 | worksheet.write_row(0, HEADERS)
30 | DATA.each_with_index do |row, i|
31 | worksheet.write_row(i + 1, row)
32 | end
33 | workbook.read_string
34 | end
35 |
36 | x.compare!
37 | end
38 |
--------------------------------------------------------------------------------
/benchmarks/init.rb:
--------------------------------------------------------------------------------
1 | require 'bundler/setup'
2 | require 'fileutils'
3 | require 'tmpdir'
4 | require_relative '../lib/fast_excel'
5 |
6 | # gem install axlsx benchmark-ips write_xlsx
7 |
8 | require "benchmark/ips"
9 | require 'axlsx'
10 | require 'write_xlsx'
11 | require 'xlsxtream'
12 | require 'process_memory'
13 |
14 | def write_fast_excel_20k
15 | workbook = FastExcel.open(constant_memory: true)
16 | worksheet = workbook.add_worksheet("benchmark")
17 |
18 | worksheet.write_row(0, HEADERS)
19 | DATA.each_with_index do |row, i|
20 | worksheet.write_row(i + 1, row)
21 | end
22 | workbook.read_string
23 | end
24 |
25 | def write_xlsx_20k
26 | filename = "#{Dir.mktmpdir}/write_xlsx.xlsx"
27 | workbook = WriteXLSX.new(filename)
28 | worksheet = workbook.add_worksheet
29 | HEADERS.each_with_index do |value, i|
30 | worksheet.write(0, i, value)
31 | end
32 | DATA.each_with_index do |row, row_num|
33 | worksheet.write_number(row_num + 1, 0, row[0])
34 | worksheet.write_string(row_num + 1, 1, row[1])
35 | worksheet.write_number(row_num + 1, 2, row[2])
36 | worksheet.write_number(row_num + 1, 3, row[3])
37 | worksheet.write_number(row_num + 1, 4, row[4])
38 | end
39 | workbook.close
40 | File.open(filename, 'rb', &:read)
41 | File.delete(filename)
42 | end
43 |
44 | def write_axlsx_20k
45 | filename = "#{Dir.mktmpdir}/axlsx.xlsx"
46 | Axlsx::Package.new do |package|
47 | package.use_autowidth = false
48 | package.workbook.add_worksheet do |sheet|
49 | sheet.add_row(HEADERS)
50 | DATA.each do |row|
51 | sheet.add_row(row)
52 | end
53 | end
54 | package.serialize(filename)
55 | File.open(filename, 'rb', &:read)
56 | File.delete(filename)
57 | end
58 | end
59 |
60 | def write_xlsxtream_20k
61 | filename = "#{Dir.mktmpdir}/xlsxtream.xlsx"
62 |
63 | Xlsxtream::Workbook.open(filename) do |xlsx|
64 | xlsx.write_worksheet do |sheet|
65 | sheet << HEADERS
66 | DATA.each do |row|
67 | sheet << row
68 | end
69 | end
70 | end
71 | end
--------------------------------------------------------------------------------
/benchmarks/memory.rb:
--------------------------------------------------------------------------------
1 | require_relative 'init'
2 |
3 | HEADERS = ["id", "name", "age", "date", "random"]
4 |
5 | DATA = []
6 | 10_000.times do |n|
7 | DATA << [n, "String string #{n}" * 5, (n * rand * 10).round, Time.at(n * 1000 + 1492922688), n * 100]
8 | end
9 |
10 | puts "warm up..."
11 | write_fast_excel_20k
12 | write_axlsx_20k
13 | write_xlsx_20k
14 | write_xlsxtream_20k
15 |
16 | DATA.clear
17 | 50_000.times do |n|
18 | DATA << [n, "String string #{n}" * 5, (n * rand * 10).round, Time.at(n * 1000 + 1492922688), n * 100]
19 | end
20 |
21 | GC.start
22 | sleep 5
23 |
24 | def measure_memory(title)
25 | puts "Running test: #{title}"
26 | recorder = ProcessMemory.start_recording
27 | yield
28 | puts recorder.print("Done!")
29 | recorder.stop
30 | puts recorder.report_per_second_pretty
31 | puts
32 | end
33 |
34 | measure_memory("FastExcel") do
35 | write_fast_excel_20k
36 | end
37 |
38 | GC.start
39 | sleep 5
40 |
41 | measure_memory("Axlsx") do
42 | write_axlsx_20k
43 | end
44 |
45 | GC.start
46 | sleep 5
47 |
48 | measure_memory("write_xlsx") do
49 | write_xlsx_20k
50 | end
51 |
52 | GC.start
53 | sleep 5
54 |
55 | measure_memory("xlsxtream") do
56 | write_xlsxtream_20k
57 | end
58 |
--------------------------------------------------------------------------------
/benchmarks/profiler.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 | require 'ruby-prof'
3 |
4 | DATA = []
5 | 1000.times do |n|
6 | DATA << [n, "String string #{n}", (n * rand * 10).round, Time.at(n * 1000 + 1492922688)]
7 | end
8 |
9 | RubyProf.start
10 |
11 | 100.times do
12 | workbook = FastExcel.open(constant_memory: true)
13 | worksheet = workbook.add_worksheet("benchmark")
14 | worksheet.auto_width = true
15 |
16 | DATA.each_with_index do |row, i|
17 | worksheet.write_row(i + 1, row)
18 | end
19 | workbook.read_string
20 |
21 | print '.'
22 | end
23 | result = RubyProf.stop
24 |
25 | # print a flat profile to text
26 | printer = RubyProf::FlatPrinter.new(result)
27 | printer.print(STDOUT)
28 |
--------------------------------------------------------------------------------
/benchmarks/write_value.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 | require "benchmark/memory"
3 | require "benchmark/ips"
4 |
5 | DATA = []
6 | 1000.times do |n|
7 | DATA << [n, "String string #{n}", (n * rand * 10).round, Time.at(n * 1000 + 1492922688)]
8 | end
9 |
10 | 5.times do
11 | workbook = FastExcel.open(constant_memory: true)
12 | worksheet = workbook.add_worksheet("benchmark")
13 |
14 | DATA.each_with_index do |row, row_num|
15 | row.each_with_index do |val, cell_num|
16 | worksheet.write_value(row_num + 1, cell_num + 1, val)
17 | end
18 | end
19 | workbook.read_string
20 | end
21 |
22 |
23 | workbook = FastExcel.open(constant_memory: true)
24 | worksheet = workbook.add_worksheet("benchmark")
25 |
26 | DATA.each_with_index do |row, row_num|
27 | row.each_with_index do |val, cell_num|
28 | worksheet.write_value(row_num + 1, cell_num + 1, val)
29 | end
30 | end
31 | workbook.read_string
32 |
33 | Benchmark.ips do |x|
34 | #x.config(time: 10, warmup: 2)
35 |
36 | x.report("Normal") do
37 | workbook = FastExcel.open(constant_memory: true)
38 | worksheet = workbook.add_worksheet("benchmark")
39 |
40 | DATA.each_with_index do |row, row_num|
41 | row.each_with_index do |val, cell_num|
42 | worksheet.write_value(row_num + 1, cell_num + 1, val)
43 | end
44 | end
45 | workbook.read_string
46 | end
47 |
48 | x.report("Auto-width") do
49 | workbook = FastExcel.open(constant_memory: true)
50 | worksheet = workbook.add_worksheet("benchmark")
51 | worksheet.auto_width = true
52 |
53 | DATA.each_with_index do |row, row_num|
54 | row.each_with_index do |val, cell_num|
55 | worksheet.write_value(row_num + 1, cell_num + 1, val)
56 | end
57 | end
58 | workbook.read_string
59 | end
60 |
61 | x.compare!
62 | end
63 |
--------------------------------------------------------------------------------
/examples/example.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | workbook = FastExcel.open("example.xlsx", constant_memory: true)
4 |
5 | workbook.default_format.set(
6 | font_size: 0, # user's default
7 | #font_family: "Arial"
8 | )
9 |
10 | # pp workbook.default_format
11 |
12 | worksheet = workbook.add_worksheet("Payments Report")
13 |
14 | bold = workbook.bold_format
15 | worksheet.set_column(0, 0, FastExcel::DEF_COL_WIDTH, bold)
16 |
17 | price = workbook.number_format("#,##0.00")
18 | worksheet.set_column(1, 1, 20, price)
19 |
20 | date_format = workbook.number_format("[$-409]m/d/yy h:mm AM/PM;@")
21 | worksheet.set_column(2, 2, 20, date_format)
22 |
23 | worksheet.write_row(0, ["message", "price", "date", "complete"], bold)
24 |
25 | worksheet.write_comment(2, 2, "Comment to field")
26 |
27 | for i in 1..1000
28 | worksheet.write_row(i, ["Hello", (rand * 10_000_000).round(2), Time.now, i % 2 == 0])
29 |
30 | # Or manually
31 | # worksheet.write_string(i, 0, "Hello", nil)
32 | # worksheet.write_number(i, 1, (rand * 10_000_000).round(2), nil)
33 | # date = Libxlsxwriter::Datetime.new
34 | # date[:year] = 2017
35 | # date[:month] = 2
36 | # date[:day] = 24
37 | # date[:hour] = i % 24
38 | # date[:min] = i % 60
39 | # date[:sec] = i % 60
40 | # worksheet.write_datetime(i, 2, date, nil)
41 | end
42 |
43 | workbook.close
44 | puts "Saved to file example.xlsx"
--------------------------------------------------------------------------------
/examples/example_align.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | workbook = FastExcel.open("example_align.xlsx", constant_memory: true)
4 |
5 | worksheet = workbook.add_worksheet
6 |
7 | row_format = workbook.add_format
8 |
9 | row_format.align = {h: :center, v: :center}
10 | # Can also be called as:
11 | # row_format.align = :align_center
12 | # row_format.align = :align_vertical_center
13 |
14 | print "Align set as: "
15 | p row_format.align # => {horizontal: :align_center, vertical: :align_vertical_center}
16 |
17 | worksheet.set_column_width(0, 30)
18 | worksheet.set_row(0, 30, row_format)
19 |
20 | worksheet.write_row(0, ["Hello"])
21 |
22 | workbook.close
23 | puts "Saved to file example_align.xlsx"
24 |
--------------------------------------------------------------------------------
/examples/example_auto_width.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | workbook = FastExcel.open("example_auto_width.xlsx", constant_memory: false)
4 |
5 | # this is required to make auto-width works correctly
6 | workbook.default_format.set(
7 | font_size: 13,
8 | font_family: "Arial"
9 | )
10 |
11 | worksheet = workbook.add_worksheet
12 | worksheet.auto_width = true
13 |
14 | ['Arial', 'Calibri', 'Times New Roman'].each_with_index do |font, index|
15 | col_format = workbook.add_format(font_family: font, font_size: 17)
16 | worksheet.set_column(index * 4, index * 4 + 3, 10, col_format)
17 |
18 | worksheet.write_value(0, index * 4 + 2, font)
19 | worksheet.write_value(1, index * 4, "tini")
20 | worksheet.write_value(1, index * 4 + 1, "Longer")
21 | worksheet.write_value(1, index * 4 + 2, "Some longer text!")
22 | worksheet.write_value(1, index * 4 + 3, "This gem is FFI binding for libxlsxwriter C library")
23 | end
24 |
25 | workbook.close
26 | puts "Saved to file example_auto_width.xlsx"
27 |
--------------------------------------------------------------------------------
/examples/example_chart.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | workbook = FastExcel.open("example_chart.xlsx", constant_memory: true)
4 | worksheet = workbook.add_worksheet
5 |
6 | for i in 0..5
7 | for n in 0..3
8 | worksheet.write_number(i, n, (i + 1) * (n + 1), nil)
9 | end
10 | end
11 |
12 | chart = workbook.add_chart(Libxlsxwriter::enum_type(:chart_type)[:column])
13 |
14 | chart.add_series("Bob", "Sheet1!$A$1:$A$5")
15 | chart.add_series("Alice", "Sheet1!$B$1:$B$5")
16 | chart.add_series("Montgomery", "Sheet1!$C$1:$C$5")
17 |
18 | worksheet.insert_chart(1, 7, chart)
19 |
20 | workbook.close
21 | puts "Saved to file example_chart.xlsx"
--------------------------------------------------------------------------------
/examples/example_colors.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | workbook = FastExcel.open("example_colors.xlsx", constant_memory: true)
4 |
5 | worksheet = workbook.add_worksheet
6 |
7 | color_format = workbook.add_format
8 |
9 | # We can use color names as string and symbols, color hex codes and color hex numbers
10 |
11 | color_format.set(
12 | font_color: '9900FF',
13 | bg_color: '#FFAAAA',
14 |
15 | border_bottom: :medium,
16 | border_bottom_color: 'green',
17 |
18 | border_left: :slant_dash_dot,
19 | border_left_color: 0x00FF00,
20 |
21 | border_right: :double,
22 | border_right_color: :crimson,
23 |
24 | border_top: :border_hair,
25 | border_top_color: :medium_blue
26 | )
27 |
28 | # Possible border styles:
29 | # [:none, :thin, :medium, :dashed, :dotted, :thick, :double, :hair, :medium_dashed,
30 | # :dash_dot, :medium_dash_dot, :dash_dot_dot, :medium_dash_dot_dot, :slant_dash_dot]
31 |
32 | worksheet.set_column_width(1, 30)
33 |
34 | worksheet.write_value(1, 1, "Hello", color_format)
35 |
36 | workbook.close
37 | puts "Saved to file example_colors.xlsx"
38 |
--------------------------------------------------------------------------------
/examples/example_date_time.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | require 'date'
4 | require 'time'
5 |
6 |
7 | File.unlink("example_date_time.xlsx") if File.exist?("example_date_time.xlsx")
8 |
9 | workbook = FastExcel.open("example_date_time.xlsx", constant_memory: true)
10 | workbook.default_format.set(
11 | font_size: 0, # user's default
12 | )
13 | worksheet = workbook.add_worksheet
14 |
15 | worksheet.set_columns_width(0, 4, 25)
16 | worksheet.set_column(1, 1, 25, workbook.number_format("[$-409]m/d/yy hh:mm;@"))
17 |
18 | intro = "Date and time in excel file stored as decimal number, it show number of days since January 1900, decimal part is for time of the day"
19 | worksheet.merge_range(0, 0, 0, 4, intro, nil)
20 | worksheet.write_value(1, 0, "")
21 |
22 | worksheet.append_row(['', 'Formatted as Date', 'No formatting, plain number'])
23 |
24 | worksheet.append_row(["Time.now", Time.now, Time.now, 'local timezone'])
25 | worksheet.append_row(["Time.now.utc", Time.now.utc, Time.now.utc, 'UTC timezone'])
26 |
27 | worksheet.append_row(["DateTime.now", DateTime.now, DateTime.now, 'local timezone'])
28 | dt = DateTime.now.new_offset("+02:00")
29 | worksheet.append_row(["DateTime new_offset", dt, dt, 'GMT+2 timezone'])
30 |
31 | today = Date.today
32 | worksheet.append_row(["Date.today", today, today])
33 |
34 | worksheet.append_row(["0 (just zero)", 0, 0, '00 January 1900'])
35 |
36 |
37 | workbook.close
38 | puts "Saved to file example_date_time.xlsx"
39 |
--------------------------------------------------------------------------------
/examples/example_filters.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | `rm example_filters.xlsx` if File.exist?('example_filters.xlsx')
4 | workbook = FastExcel.open("example_filters.xlsx", constant_memory: false)
5 |
6 | workbook.default_format.set(
7 | font_size: 0, # user's default
8 | #font_family: "Arial"
9 | )
10 |
11 | # pp workbook.default_format
12 |
13 | worksheet = workbook.add_worksheet("Payments Report")
14 |
15 | # p worksheet[:filter_on]
16 | # FastExcel.print_ffi_obj(worksheet)
17 |
18 | bold = workbook.bold_format
19 | worksheet.set_column(0, 0, FastExcel::DEF_COL_WIDTH, bold)
20 |
21 | price = workbook.number_format("#,##0.00")
22 | worksheet.set_column(1, 1, 20, price)
23 |
24 | date_format = workbook.number_format("[$-409]m/d/yy h:mm AM/PM;@")
25 | worksheet.set_column(2, 2, 20, date_format)
26 |
27 | worksheet.write_row(0, ["message", "price", "date", "complete"], bold)
28 |
29 | for i in 1..1000
30 | worksheet.write_row(i, ["Hello", (rand * 10_000_000).round(2), Time.now, i % 2 == 0])
31 | end
32 |
33 | worksheet.enable_filters!(end_col: 3)
34 |
35 | workbook.close
36 | puts "Saved to file example_filters.xlsx"
--------------------------------------------------------------------------------
/examples/example_formula.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | workbook = FastExcel.open("example_formula.xlsx", constant_memory: false)
4 |
5 | worksheet = workbook.add_worksheet
6 |
7 | worksheet.write_row(0, ["Item", "Weight"])
8 | worksheet.write_row(1, ["Laptop", 1.37])
9 | worksheet.write_row(2, ["Phone", 0.138])
10 | worksheet.write_row(3, ["Mouse", 0.099])
11 | worksheet.write_row(4, ["Speaker", 2.5])
12 | worksheet.write_row(5, ["Camera", 0.383])
13 | worksheet.write_row(6, ["Total", FastExcel::Formula.new("SUM(B2:B6)")], workbook.bold_format)
14 |
15 | workbook.close
16 | puts "Saved to file example_formula.xlsx"
17 |
--------------------------------------------------------------------------------
/examples/example_hyperlink.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | workbook = FastExcel.open("example_hyperlink.xlsx", constant_memory: false)
4 | worksheet = workbook.add_worksheet
5 | worksheet.auto_width = true
6 |
7 | url_format = workbook.add_format(underline: :underline_single, font_color: :blue)
8 |
9 | worksheet.append_row([
10 | "Ultra Fast Excel Writer for Ruby",
11 | FastExcel::URL.new("https://github.com/Paxa/fast_excel"),
12 | FastExcel::URL.new("postgres://localhost")
13 | ], [nil, url_format])
14 |
15 | # Same as:
16 | # worksheet.write_value(0, 0, "Ultra Fast Excel Writer for Ruby")
17 | # worksheet.write_url(0, 1, "https://github.com/Paxa/fast_excel", url_format)
18 |
19 | workbook.close
20 | puts "Saved to file example_hyperlink.xlsx"
21 |
--------------------------------------------------------------------------------
/examples/example_image.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | workbook = FastExcel.open("example_image.xlsx", constant_memory: false)
4 | worksheet = workbook.add_worksheet
5 |
6 | img_options = Libxlsxwriter::ImageOptions.new
7 | img_options[:x_offset] = 0
8 | img_options[:y_offset] = 0
9 |
10 | worksheet.insert_image_opt(3, 3, "examples/logo.png", img_options)
11 |
12 | workbook.close
13 | puts "Saved to file example_image.xlsx"
--------------------------------------------------------------------------------
/examples/example_styles.rb:
--------------------------------------------------------------------------------
1 | require_relative '../lib/fast_excel'
2 |
3 | workbook = FastExcel.open("example_styles.xlsx", constant_memory: true)
4 |
5 | #workbook.default_format.set(
6 | # font_size: 0, # user's default
7 | # #font_family: "Arial"
8 | #)
9 |
10 | worksheet = workbook.add_worksheet
11 |
12 | worksheet.set_columns_width(0, 11, 11)
13 |
14 | worksheet.write_value(0, 0, "Bold", workbook.add_format(bold: true))
15 | worksheet.write_value(0, 1, "Italic", workbook.add_format(italic: true))
16 | worksheet.write_value(0, 2, "Underline", workbook.add_format(underline: :underline_single))
17 | worksheet.write_value(0, 3, "Double line", workbook.add_format(underline: :underline_double))
18 | worksheet.write_value(0, 4, "Indent", workbook.add_format(indent: 1))
19 | worksheet.write_value(0, 5, "Border", workbook.add_format(border: :border_thin))
20 | worksheet.write_value(0, 6, "Border2", workbook.add_format(border: :border_medium))
21 | worksheet.write_value(0, 7, "Pattern", workbook.add_format(pattern: :pattern_light_up, bg_color: :yellow))
22 | worksheet.write_value(0, 8, "Script", workbook.add_format(font_script: :font_subscript))
23 | worksheet.write_value(0, 9, "Strike", workbook.add_format(font_strikeout: true))
24 | worksheet.write_value(0, 10, "Shaddow", workbook.add_format(font_shadow: true))
25 |
26 | workbook.close
27 | puts "Saved to file example_styles.xlsx"
--------------------------------------------------------------------------------
/examples/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Paxa/fast_excel/dc2b5e56e28a26e5f601fde98233a0241a4c4ebd/examples/logo.png
--------------------------------------------------------------------------------
/ext/fast_excel/extconf.rb:
--------------------------------------------------------------------------------
1 | require 'mkmf'
2 |
3 | create_makefile('ext/text_width_ext')
--------------------------------------------------------------------------------
/extconf.rb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Paxa/fast_excel/dc2b5e56e28a26e5f601fde98233a0241a4c4ebd/extconf.rb
--------------------------------------------------------------------------------
/fast_excel.gemspec:
--------------------------------------------------------------------------------
1 | Gem::Specification.new do |s|
2 | s.name = "fast_excel"
3 | s.version = "0.5.0"
4 | s.author = ["Pavel Evstigneev"]
5 | s.email = ["pavel.evst@gmail.com"]
6 | s.homepage = "https://github.com/paxa/fast_excel"
7 | s.summary = %q{Ultra Fast Excel Writer}
8 | s.description = "Wrapper for libxlsxwriter using ffi"
9 | s.license = 'MIT'
10 | s.required_ruby_version = ['>= 2.0']
11 |
12 | s.files = `git ls-files`.split("\n")
13 | s.test_files = []
14 |
15 | s.require_paths = ["lib"]
16 | s.extensions = ["extconf.rb"]
17 |
18 | s.add_runtime_dependency "ffi", ["> 1.17", "< 2"]
19 | s.add_runtime_dependency "base64", [">= 0.2", "< 2"]
20 | end
21 |
--------------------------------------------------------------------------------
/letters.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
18 |
19 |
20 |
21 |
22 |
23 |
115 |
--------------------------------------------------------------------------------
/libxlsxwriter/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | custom: ["paypal.me/xlsxwriter"]
2 |
--------------------------------------------------------------------------------
/libxlsxwriter/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | # libxlsxwriter: Reporting Bugs
2 |
3 | Here are some tips on reporting bugs in `libxlsxwriter`.
4 |
5 | ### Upgrade to the latest version of the library
6 |
7 | Upgrade to the latest version of the library since the bug you are reporting
8 | may already be fixed.
9 |
10 | Check the [Changes][changes] section of the documentation to see what has
11 | changed in the latest versions.
12 |
13 | [changes]: http://libxlsxwriter.github.io/changes.html
14 |
15 | You can check which version of `libxlsxwriter` that you are using by checking
16 | the `xlsxwriter.h` header file or by adding the following to your program:
17 |
18 | ```C
19 | #include
20 | #include "xlsxwriter.h"
21 |
22 | int main() {
23 |
24 | printf("Libxlsxwriter version = %s\n", lxw_version());
25 |
26 | return 0;
27 | }
28 | ```
29 |
30 | ### Read the documentation
31 |
32 | Read or search the `libxlsxwriter` [documentation][docs] to see if the issue
33 | you are encountering is already explained.
34 |
35 | [docs]: http://libxlsxwriter.github.io/index.html
36 |
37 | ### Look at the example programs
38 |
39 | There are many [examples programs][examples] in the distribution. Try to
40 | identify an example program that corresponds to your query and adapt it to use
41 | as a bug report.
42 |
43 | [examples]: http://libxlsxwriter.github.io/examples.html
44 |
45 |
46 | ### Tips for submitting a bug report
47 |
48 | 1. Describe the problem as clearly and as concisely as possible.
49 | 2. Include a sample program. This is probably the most important step.
50 | It is generally easier to describe a problem in code than in written
51 | prose.
52 | 3. The sample program should be as small as possible to demonstrate the
53 | problem. Don't copy and paste large non-relevant sections of your
54 | program.
55 |
56 | A sample bug report is shown below. This format helps analyze and respond to
57 | the bug report more quickly.
58 |
59 |
60 | > Subject: Issue with SOMETHING
61 | >
62 | > Greetings,
63 | >
64 | > I am using libxlsxwriter to do SOMETHING but it appears to do SOMETHING ELSE.
65 | >
66 | > I am using CC version X.Y.Z, OS = uname and libxlsxwriter x.y.z.
67 | >
68 | > Here is some code that demonstrates the problem:
69 | >
70 | >
71 | >```C
72 | >#include "xlsxwriter.h"
73 | >
74 | >int main() {
75 | >
76 | > lxw_workbook *workbook = workbook_new("bug_report.xlsx");
77 | > lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
78 | >
79 | > worksheet_write_string(worksheet, 0, 0, "Hello", NULL);
80 | > worksheet_write_number(worksheet, 1, 0, 123, NULL);
81 | >
82 | > return workbook_close(workbook);
83 | >}
84 | >```
85 | >
86 |
--------------------------------------------------------------------------------
/libxlsxwriter/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | # libxlsxwriter: Submitting Pull Requests
2 |
3 | # Pull Requests and Contributing to Libxlsxwriter
4 |
5 | All patches and pull requests are welcome but in general you should start with
6 | an issue tracker to describe what you intend to do before you do it.
7 |
8 |
9 | ### Getting Started
10 |
11 | 1. Pull requests and new feature proposals must start with an [issue
12 | tracker][issues]. This serves as the focal point for the design discussion.
13 | 2. Describe what you plan to do. If there are API changes add some code
14 | example to demonstrate them.
15 | 3. Fork the repository.
16 | 4. Run all the tests to make sure the current code works on your system using
17 | `make test`. See the [Running the Test Suite][tests] section of the docs
18 | for instructions.
19 | 5. Create a feature branch for your new feature.
20 |
21 |
22 | [tests]: http://libxlsxwriter.github.io/running_the_tests.html
23 |
24 | ### Code Style
25 |
26 | The code style is mainly K&R style with 4 space indents.
27 |
28 | The author uses GNU indent (`gindent`) 2.2.10 with the following options:
29 |
30 | ```
31 | --braces-on-if-line
32 | --braces-on-struct-decl-line
33 | --case-indentation 4
34 | --continue-at-parentheses
35 | --declaration-comment-column 0
36 | --format-first-column-comments
37 | --honour-newlines
38 | --ignore-profile
39 | --indent-label 0
40 | --indent-level 4
41 | --no-space-after-function-call-names
42 | --no-tabs
43 | --swallow-optional-blank-lines
44 | ```
45 |
46 | The [indent configuration file][indentpro] is available in the repo. The code
47 | can be indented automatically if the same version of `gindent` is used with
48 | the following make command:
49 |
50 | ```shell
51 | make indent
52 | ```
53 |
54 | Note, make sure you have backed up your files or added them to the index
55 | before running this command.
56 |
57 | In general follow the existing style in the code.
58 |
59 | [indentpro]: https://github.com/jmcnamara/libxlsxwriter/blob/master/.indent.pro
60 |
61 | ### Writing and Running Tests
62 |
63 | Any significant features should be accompanied by a test. See the `test`
64 | directory and the [Running the Test Suite][tests] section of the docs for
65 | details of the test setup.
66 |
67 | The tests can be run as follows:
68 |
69 | ```shell
70 | make test
71 | ```
72 | Same as:
73 |
74 | ```shell
75 | make test_unit
76 | make test_functional
77 | ```
78 |
79 | The functional tests require the Python module [pytest][pytest] as a test runner.
80 |
81 | If you have `valgrind` installed you can use the test suite to check for memory leaks:
82 |
83 | ```shell
84 | make test_valgrind
85 | ```
86 |
87 | When you push your changes they will also be tested automatically using
88 | [GitHub Actions][actions].
89 |
90 | [actions]: https://github.com/jmcnamara/libxlsxwriter/actions
91 | [pytest]: http://pytest.org/
92 |
93 |
94 | ### Documentation
95 |
96 | The `libxlsxwriter` documentation is written in Doxygen format in the header
97 | files and in additional `.dox` files in the `docs/src` directory of the
98 | repo. The documentation can be built as follows:
99 |
100 | ```shell
101 | make docs
102 | open docs/html/index.html
103 | ```
104 |
105 |
106 | ### Example programs
107 |
108 | If applicable add an example program to the `examples` directory. Example
109 | files can be built using:
110 |
111 | ```shell
112 | make docs
113 | ```
114 |
115 | ### Copyright and License
116 |
117 | Copyright remains with the original author. Do not include additional
118 | copyright claims or Licensing requirements. GitHub and the `git` repository
119 | will record your contribution and it will be acknowledged it in the Changes
120 | file.
121 |
122 |
123 | ### Submitting the Pull Request
124 |
125 | If your change involves several incremental `git` commits then `rebase` or
126 | `squash` them onto another branch so that the Pull Request is a single commit
127 | or a small number of logical commits.
128 |
129 | Push your changes to GitHub and submit the Pull Request with a hash link to
130 | the to the Issue tracker that was opened above.
131 |
--------------------------------------------------------------------------------
/libxlsxwriter/.github/workflows/cmake_actions.yml:
--------------------------------------------------------------------------------
1 | name: Test CMake build
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | name:
8 | Cmake
9 | strategy:
10 | fail-fast: false
11 | matrix:
12 | cc: [gcc, clang]
13 | cmake_flags: ["",
14 | "-DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON",
15 | "-DUSE_DTOA_LIBRARY=ON -DBUILD_TESTS=ON",
16 | "-DUSE_MEM_FILE=ON -DBUILD_TESTS=ON",
17 | "-DUSE_NO_MD5=ON -DBUILD_TESTS=ON",
18 | "-DUSE_OPENSSL_MD5=ON -DBUILD_TESTS=ON",
19 | "-DUSE_STANDARD_TMPFILE=ON -DBUILD_TESTS=ON",
20 | "-DUSE_SYSTEM_MINIZIP=ON -DBUILD_TESTS=ON",
21 | "-DUSE_SYSTEM_MINIZIP=ON -DUSE_OPENSSL_MD5=ON -DBUILD_TESTS=ON"]
22 | runs-on: ubuntu-latest
23 | env:
24 | CC: ${{ matrix.cc }}
25 |
26 | steps:
27 | - uses: actions/checkout@v2
28 |
29 | - name: Install dependencies
30 | run: |
31 | python -m pip install --upgrade pip
32 | pip install pytest
33 | sudo apt update
34 | sudo apt-get -y install zlib1g-dev
35 | sudo apt-get -y install libminizip-dev
36 | sudo apt-get -y install libssl-dev
37 |
38 | - name: Configure CMake
39 | working-directory: ${{ github.workspace }}/cmake
40 | run: cmake .. -DBUILD_TESTS=ON ${{ matrix.cmake_flags }} -DCMAKE_BUILD_TYPE=Release
41 |
42 | - name: Build
43 | working-directory: ${{ github.workspace }}/cmake
44 | run: cmake --build . --config Release --parallel
45 |
46 | - name: Test
47 | working-directory: ${{ github.workspace }}/cmake
48 | run: ctest -C Release -V
49 |
--------------------------------------------------------------------------------
/libxlsxwriter/.github/workflows/code_style.yml:
--------------------------------------------------------------------------------
1 | name: Check code style
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | name:
8 | Check code style
9 |
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v2
14 |
15 | - name: Install dependencies
16 | run: |
17 | sudo apt-get -y install indent
18 | sudo ln -s /usr/bin/indent /usr/bin/gindent
19 |
20 | - name: Make indent
21 | run: |
22 | make indent
23 | git status | grep 'nothing to commit'
24 |
--------------------------------------------------------------------------------
/libxlsxwriter/.github/workflows/coverity.yml:
--------------------------------------------------------------------------------
1 | name: Coverity Scan
2 |
3 | on:
4 | push:
5 | branches: [coverity]
6 |
7 | jobs:
8 | coverity:
9 | runs-on: ubuntu-latest
10 | steps:
11 |
12 | - uses: actions/checkout@v2
13 |
14 | - name: Build third party libs to exclude them from scan
15 | run: make third_party
16 |
17 | - uses: vapier/coverity-scan-action@v1
18 | with:
19 | project: libxlsxwriter
20 | email: ${{ secrets.COVERITY_SCAN_EMAIL }}
21 | token: ${{ secrets.COVERITY_SCAN_TOKEN }}
22 | command: make -C src libxlsxwriter.a
23 |
--------------------------------------------------------------------------------
/libxlsxwriter/.github/workflows/make_actions.yml:
--------------------------------------------------------------------------------
1 | name: Test Make build
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | name:
8 | Make
9 | strategy:
10 | fail-fast: false
11 | matrix:
12 | cc: [gcc, clang]
13 | make_flags: ["",
14 | "USE_STANDARD_TMPFILE=1",
15 | "USE_SYSTEM_MINIZIP=1",
16 | "USE_DTOA_LIBRARY=1",
17 | "USE_NO_MD5=1",
18 | "USE_OPENSSL_MD5=1",
19 | "USE_MEM_FILE=1"]
20 | runs-on: ubuntu-latest
21 | env:
22 | CC: ${{ matrix.cc }}
23 | CXX: ${{ matrix.cc }}
24 | CFLAGS: '-Werror'
25 |
26 | steps:
27 | - uses: actions/checkout@v2
28 |
29 | - name: Install dependencies
30 | run: |
31 | python -m pip install --upgrade pip
32 | pip install pytest
33 | sudo apt update
34 | sudo apt-get -y install zlib1g-dev
35 | sudo apt-get -y install libminizip-dev
36 | sudo apt-get -y install libssl-dev
37 | sudo apt-get -y install valgrind
38 |
39 | - name: make
40 | run: ${{ matrix.make_flags }} make V=1
41 |
42 | - name: test unit
43 | run: ${{ matrix.make_flags }} make test_unit V=1
44 |
45 | - name: test functional
46 | run: ${{ matrix.make_flags }} make test_functional V=1 -j
47 |
48 | - name: test cpp
49 | run: ${{ matrix.make_flags }} make test_cpp V=1
50 |
51 | - name: test examples
52 | run: ${{ matrix.make_flags }} make examples V=1
53 |
--------------------------------------------------------------------------------
/libxlsxwriter/.github/workflows/valgrind.yml:
--------------------------------------------------------------------------------
1 | name: Test for memory leaks
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | name:
8 | Valgrind
9 | runs-on: ubuntu-latest
10 | env:
11 | CC: gcc
12 |
13 | steps:
14 | - uses: actions/checkout@v2
15 |
16 | - name: Install dependencies
17 | run: |
18 | sudo apt update
19 | sudo apt-get -y install valgrind
20 | sudo apt-get -y install zlib1g-dev
21 |
22 | - name: test valgrind
23 | run: make test_valgrind V=1 -j 2
24 |
--------------------------------------------------------------------------------
/libxlsxwriter/.github/workflows/windows_build.yml:
--------------------------------------------------------------------------------
1 | name: Test Cmake build on Windows
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | name: CMake on Windows
8 |
9 | strategy:
10 | fail-fast: false
11 | matrix:
12 | cmake_flags: ["-DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON",
13 | "-DUSE_DTOA_LIBRARY=ON -DBUILD_TESTS=ON",
14 | #"-DUSE_SYSTEM_MINIZIP=ON -DBUILD_TESTS=ON",
15 | #"-DUSE_SYSTEM_MINIZIP=ON -DUSE_OPENSSL_MD5=ON -DBUILD_TESTS=ON",
16 | "-DUSE_OPENSSL_MD5=ON -DBUILD_TESTS=ON",
17 | ]
18 |
19 | runs-on: windows-latest
20 |
21 | steps:
22 | - uses: actions/checkout@v2
23 |
24 | - name: Install dependencies
25 | working-directory: ${{env.GITHUB_WORKSPACE}}
26 | shell: cmd
27 | run: |
28 | vcpkg.exe install zlib:x64-windows minizip:x64-windows openssl:x64-windows
29 | vcpkg.exe integrate install
30 | pip install pytest
31 |
32 | - name: Configure CMake
33 | working-directory: ${{env.GITHUB_WORKSPACE}}
34 | shell: cmd
35 | run: |
36 | cd cmake
37 | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
38 | cmake .. -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_flags }} -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -A x64
39 |
40 | - name: Build
41 | working-directory: ${{env.GITHUB_WORKSPACE}}
42 | shell: cmd
43 | run: |
44 | cd cmake
45 | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
46 | cmake --build . --config Release
47 |
48 | - name: Test
49 | working-directory: ${{env.GITHUB_WORKSPACE}}
50 | shell: cmd
51 | run: |
52 | cd cmake
53 | copy test\functional\src\Release\*.exe test\functional\src
54 | pytest -v test/functional
55 |
--------------------------------------------------------------------------------
/libxlsxwriter/.github/workflows/zig_build.yml:
--------------------------------------------------------------------------------
1 | name: Zig Build
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | strategy:
8 | fail-fast: false
9 | matrix:
10 | runs-on: [ubuntu-latest, macos-latest, windows-latest]
11 | runs-on: ${{ matrix.runs-on }}
12 | steps:
13 | - uses: actions/checkout@v4
14 | with:
15 | submodules: recursive
16 | fetch-depth: 0
17 | - uses: goto-bus-stop/setup-zig@v2
18 | with:
19 | version: 0.11.0
20 |
21 | - name: Build Summary
22 | run: zig build -DBUILD_TESTS -DBUILD_EXAMPLES -DUSE_SYSTEM_MINIZIP --summary all -freference-trace
23 |
--------------------------------------------------------------------------------
/libxlsxwriter/.gitignore:
--------------------------------------------------------------------------------
1 | *.a
2 | *.o
3 | *.so
4 | *.so.*
5 | *.to
6 | *.lo
7 | *.la
8 | *.dylib
9 | *.dll
10 | *.gcno
11 | *.gcda
12 | test_*
13 | !test_*.c
14 | !test_*.cpp
15 | !test_*.py
16 | *.tar.gz
17 | *~
18 | TAGS
19 | .#*
20 | *#
21 | ~*xlsx
22 | *.xlsx
23 | *.bak
24 | !test/functional/xlsx_files/*.xlsx
25 | *.pyc
26 | .pytest_cache/
27 | .cproject
28 | .project
29 | .pydevproject
30 | .settings/
31 | .DS_Store
32 | __pycache__
33 | .cache
34 | docs/html
35 | docs/latex
36 | .deps
37 | .dirstamp
38 | _temp.c
39 | examples/*
40 | !examples/*.c
41 | !examples/*.png
42 | !examples/Makefile
43 | !examples/vbaProject.bin
44 | cov-int
45 | libxlsxwriter-coverity.tgz
46 | build
47 |
48 | third_party/zlib-1.2.8/configure.log
49 | third_party/zlib-1.2.8/contrib/minizip/miniunz
50 | third_party/zlib-1.2.8/contrib/minizip/minizip
51 | third_party/zlib-1.2.8/example
52 | third_party/zlib-1.2.8/examplesh
53 | third_party/zlib-1.2.8/minigzip
54 | third_party/zlib-1.2.8/minigzipsh
55 | third_party/zlib-1.2.8/zlib.pc
56 |
57 | cmake
58 | !cmake/FindMINIZIP.cmake
59 | !cmake/FindPackage.cmake
60 | !cmake/i686-toolchain.cmake
61 |
62 | .vscode
63 |
64 | zig-cache/
65 | zig-out/
--------------------------------------------------------------------------------
/libxlsxwriter/.indent.pro:
--------------------------------------------------------------------------------
1 | /*
2 | * Indent rules for libxlsxwriter.
3 | *
4 | * The rules for user defined typedefs can be update as follows:
5 | *
6 | perl -i -pe 'print and last if /[l]ibxlsxwriter typedefs/' .indent.pro
7 | ack -h typedef include/xlsxwriter/*.h src/*.c | perl -lne 'print "-T $1" if /\w+\s+\w+\s+(\w+)/' | sort >> .indent.pro
8 | *
9 | */
10 |
11 | /* Command line options used with GNU indent 2.2.10 */
12 | --braces-on-if-line
13 | --braces-on-struct-decl-line
14 | --case-indentation 4
15 | --continue-at-parentheses
16 | --declaration-comment-column 0
17 | --format-first-column-comments
18 | --honour-newlines
19 | --ignore-profile
20 | --indent-label 0
21 | --indent-level 4
22 | --no-space-after-function-call-names
23 | --no-tabs
24 | --swallow-optional-blank-lines
25 |
26 | /* Typedefs used in the code. */
27 | -T int8_t
28 | -T int16_t
29 | -T int32_t
30 | -T int64_t
31 | -T uint8_t
32 | -T uint16_t
33 | -T uint32_t
34 | -T uint64_t
35 | -T ssize_t
36 | -T size_t
37 | -T time_t
38 |
39 | -T LIST_ENTRY
40 | -T RB_ENTRY
41 | -T SLIST_ENTRY
42 | -T STAILQ_ENTRY
43 | -T TAILQ_ENTRY
44 |
45 | /* libxlsxwriter typedefs. */
46 | -T lxw_app
47 | -T lxw_author_id
48 | -T lxw_autofilter
49 | -T lxw_border
50 | -T lxw_button_options
51 | -T lxw_cell
52 | -T lxw_chart
53 | -T lxw_chart_axis
54 | -T lxw_chart_axis_display_unit
55 | -T lxw_chart_axis_label_alignment
56 | -T lxw_chart_axis_label_position
57 | -T lxw_chart_axis_tick_mark
58 | -T lxw_chart_axis_tick_position
59 | -T lxw_chart_axis_type
60 | -T lxw_chart_blank
61 | -T lxw_chart_custom_label
62 | -T lxw_chart_data_label
63 | -T lxw_chart_error_bar_axis
64 | -T lxw_chart_error_bar_cap
65 | -T lxw_chart_error_bar_direction
66 | -T lxw_chart_error_bar_type
67 | -T lxw_chart_fill
68 | -T lxw_chart_font
69 | -T lxw_chart_gridline
70 | -T lxw_chart_label_position
71 | -T lxw_chart_label_separator
72 | -T lxw_chart_legend
73 | -T lxw_chart_legend_position
74 | -T lxw_chart_line
75 | -T lxw_chart_line_dash_type
76 | -T lxw_chart_marker
77 | -T lxw_chart_marker_type
78 | -T lxw_chart_options
79 | -T lxw_chart_pattern
80 | -T lxw_chart_pattern_type
81 | -T lxw_chart_point
82 | -T lxw_chart_series
83 | -T lxw_chart_title
84 | -T lxw_chart_trendline_type
85 | -T lxw_chart_type
86 | -T lxw_chartsheet
87 | -T lxw_chartsheet_name
88 | -T lxw_col_options
89 | -T lxw_col_t
90 | -T lxw_color_t
91 | -T lxw_comment
92 | -T lxw_comment_options
93 | -T lxw_cond_format_hash_element
94 | -T lxw_cond_format_obj
95 | -T lxw_conditional_format
96 | -T lxw_content_types
97 | -T lxw_core
98 | -T lxw_custom
99 | -T lxw_custom_property
100 | -T lxw_data_val_obj
101 | -T lxw_data_validation
102 | -T lxw_datetime
103 | -T lxw_defined_name
104 | -T lxw_doc_properties
105 | -T lxw_drawing
106 | -T lxw_drawing_coords
107 | -T lxw_drawing_object
108 | -T lxw_drawing_rel_id
109 | -T lxw_error
110 | -T lxw_fill
111 | -T lxw_filter_rule
112 | -T lxw_filter_rule_obj
113 | -T lxw_font
114 | -T lxw_format
115 | -T lxw_hash_element
116 | -T lxw_hash_table
117 | -T lxw_header_footer_options
118 | -T lxw_heading_pair
119 | -T lxw_image_md5
120 | -T lxw_image_options
121 | -T lxw_merged_range
122 | -T lxw_metadata
123 | -T lxw_object_properties
124 | -T lxw_packager
125 | -T lxw_panes
126 | -T lxw_part_name
127 | -T lxw_print_area
128 | -T lxw_protection
129 | -T lxw_protection_obj
130 | -T lxw_rel_tuple
131 | -T lxw_relationships
132 | -T lxw_repeat_cols
133 | -T lxw_repeat_rows
134 | -T lxw_rich_string_tuple
135 | -T lxw_row
136 | -T lxw_row_col_options
137 | -T lxw_row_t
138 | -T lxw_selection
139 | -T lxw_series_data_point
140 | -T lxw_series_error_bars
141 | -T lxw_series_range
142 | -T lxw_sheet
143 | -T lxw_sst
144 | -T lxw_styles
145 | -T lxw_table
146 | -T lxw_table_column
147 | -T lxw_table_obj
148 | -T lxw_table_options
149 | -T lxw_theme
150 | -T lxw_tuple
151 | -T lxw_vml
152 | -T lxw_vml_obj
153 | -T lxw_workbook
154 | -T lxw_workbook_options
155 | -T lxw_worksheet
156 | -T lxw_worksheet_init_data
157 | -T lxw_worksheet_name
158 |
--------------------------------------------------------------------------------
/libxlsxwriter/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # libxlsxwriter: Reporting Bugs and submitting Pull Requests
2 |
3 |
4 | ## Reporting Bugs
5 |
6 | Here are some tips on reporting bugs in `libxlsxwriter`.
7 |
8 | ### Upgrade to the latest version of the library
9 |
10 | Upgrade to the latest version of the library since the bug you are reporting
11 | may already be fixed.
12 |
13 | Check the [Changes][changes] section of the documentation to see what has
14 | changed in the latest versions.
15 |
16 | [changes]: http://libxlsxwriter.github.io/changes.html
17 |
18 | You can check which version of `libxlsxwriter` that you are using by checking
19 | the `xlsxwriter.h` header file or by adding the following to your program:
20 |
21 | ```C
22 | #include
23 | #include "xlsxwriter.h"
24 |
25 | int main() {
26 |
27 | printf("Libxlsxwriter version = %s\n", lxw_version());
28 |
29 | return 0;
30 | }
31 | ```
32 |
33 |
34 | ### Read the documentation
35 |
36 | Read or search the `libxlsxwriter` [documentation][docs] to see if the issue
37 | you are encountering is already explained.
38 |
39 | [docs]: http://libxlsxwriter.github.io/index.html
40 |
41 | ### Look at the example programs
42 |
43 | There are many [examples programs][examples] in the distribution. Try to
44 | identify an example program that corresponds to your query and adapt it to use
45 | as a bug report.
46 |
47 | [examples]: http://libxlsxwriter.github.io/examples.html
48 |
49 |
50 | ### Use the xlsxwriter Issue Tracker
51 |
52 | The [libxlsxwriter issue tracker][issues] is on GitHub.
53 |
54 | [issues]: https://github.com/jmcnamara/libxlsxwriter/issues
55 |
56 |
57 | ### Tips for submitting a bug report
58 |
59 | 1. Describe the problem as clearly and as concisely as possible.
60 | 2. Include a sample program. This is probably the most important step.
61 | It is generally easier to describe a problem in code than in written
62 | prose.
63 | 3. The sample program should be as small as possible to demonstrate the
64 | problem. Don't copy and paste large non-relevant sections of your
65 | program.
66 |
67 | A sample bug report is shown below. This format helps analyze and respond to
68 | the bug report more quickly.
69 |
70 |
71 | > Subject: Issue with SOMETHING
72 | >
73 | > Greetings,
74 | >
75 | > I am using libxlsxwriter to do SOMETHING but it appears to do SOMETHING ELSE.
76 | >
77 | > I am using CC version X.Y.Z, OS = uname and libxlsxwriter x.y.z.
78 | >
79 | > Here is some code that demonstrates the problem:
80 | >
81 | >
82 | >```C
83 | >#include "xlsxwriter.h"
84 | >
85 | >int main() {
86 | >
87 | > lxw_workbook *workbook = workbook_new("bug_report.xlsx");
88 | > lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
89 | >
90 | > worksheet_write_string(worksheet, 0, 0, "Hello", NULL);
91 | > worksheet_write_number(worksheet, 1, 0, 123, NULL);
92 | >
93 | > return workbook_close(workbook);
94 | >}
95 | >```
96 | >
97 |
98 |
99 | # Pull Requests and Contributing to Libxlsxwriter
100 |
101 | All patches and pull requests are welcome but in general you should start with
102 | an issue tracker to describe what you intend to do before you do it.
103 |
104 |
105 | ### Getting Started
106 |
107 | 1. Pull requests and new feature proposals must start with an [issue
108 | tracker][issues]. This serves as the focal point for the design discussion.
109 | 2. Describe what you plan to do. If there are API changes add some code
110 | example to demonstrate them.
111 | 3. Fork the repository.
112 | 4. Run all the tests to make sure the current code works on your system using
113 | `make test`. See the [Running the Test Suite][tests] section of the docs
114 | for instructions.
115 | 5. Create a feature branch for your new feature.
116 |
117 |
118 | [tests]: http://libxlsxwriter.github.io/running_the_tests.html
119 |
120 | ### Code Style
121 |
122 | The code style is mainly K&R style with 4 space indents.
123 |
124 | The author uses GNU indent (`gindent`) 2.2.10 with the following options:
125 |
126 | ```
127 | --braces-on-if-line
128 | --braces-on-struct-decl-line
129 | --case-indentation 4
130 | --continue-at-parentheses
131 | --declaration-comment-column 0
132 | --format-first-column-comments
133 | --honour-newlines
134 | --ignore-profile
135 | --indent-label 0
136 | --indent-level 4
137 | --no-space-after-function-call-names
138 | --no-tabs
139 | --swallow-optional-blank-lines
140 | ```
141 |
142 | The [indent configuration file][indentpro] is available in the repo. The code
143 | can be indented automatically if the same version of `gindent` is used with
144 | the following make command:
145 |
146 | ```shell
147 | make indent
148 | ```
149 |
150 | Note, make sure you have backed up your files or added them to the index
151 | before running this command.
152 |
153 | In general follow the existing style in the code.
154 |
155 | [indentpro]: https://github.com/jmcnamara/libxlsxwriter/blob/master/.indent.pro
156 |
157 | ### Writing and Running Tests
158 |
159 | Any significant features should be accompanied by a test. See the `test`
160 | directory and the [Running the Test Suite][tests] section of the docs for
161 | details of the test setup.
162 |
163 | The tests can be run as follows:
164 |
165 | ```shell
166 | make test
167 | ```
168 | Same as:
169 |
170 | ```shell
171 | make test_unit
172 | make test_functional
173 | ```
174 |
175 | The functional tests require the Python module [pytest][pytest] as a test runner.
176 |
177 | If you have `valgrind` installed you can use the test suite to check for memory leaks:
178 |
179 | ```shell
180 | make test_valgrind
181 | ```
182 |
183 | When you push your changes they will also be tested automatically using
184 | [GitHub Actions][actions].
185 |
186 | [actions]: https://github.com/jmcnamara/libxlsxwriter/actions
187 | [pytest]: http://pytest.org/
188 |
189 |
190 | ### Documentation
191 |
192 | The `libxlsxwriter` documentation is written in Doxygen format in the header
193 | files and in additional `.dox` files in the `docs/src` directory of the
194 | repo. The documentation can be built as follows:
195 |
196 | ```shell
197 | make docs
198 | open docs/html/index.html
199 | ```
200 |
201 |
202 | ### Example programs
203 |
204 | If applicable add an example program to the `examples` directory. Example
205 | files can be built using:
206 |
207 | ```shell
208 | make docs
209 | ```
210 |
211 | ### Copyright and License
212 |
213 | Copyright remains with the original author. Do not include additional
214 | copyright claims or Licensing requirements. GitHub and the `git` repository
215 | will record your contribution and it will be acknowledged it in the Changes
216 | file.
217 |
218 |
219 | ### Submitting the Pull Request
220 |
221 | If your change involves several incremental `git` commits then `rebase` or
222 | `squash` them onto another branch so that the Pull Request is a single commit
223 | or a small number of logical commits.
224 |
225 | Push your changes to GitHub and submit the Pull Request with a hash link to
226 | the to the Issue tracker that was opened above.
227 |
--------------------------------------------------------------------------------
/libxlsxwriter/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.7
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "libxlsxwriter",
8 | products: [
9 | .library(
10 | name: "libxlsxwriter",
11 | targets: ["libxlsxwriter"]),
12 | ],
13 | targets: [
14 | .target(
15 | name: "libxlsxwriter",
16 | path: ".",
17 | exclude: [
18 | "src/Makefile",
19 | ],
20 | sources: [
21 | "include",
22 | "src",
23 | "third_party/minizip/zip.c",
24 | "third_party/minizip/ioapi.c",
25 | "third_party/tmpfileplus/tmpfileplus.c",
26 | "third_party/md5/md5.c"
27 | ],
28 | publicHeadersPath: "include",
29 | linkerSettings: [
30 | .linkedLibrary("z")
31 | ]),
32 | .testTarget(
33 | name: "libxlsxwritertests",
34 | dependencies: ["libxlsxwriter"],
35 | path: ".",
36 | sources: ["test/swift"],
37 | linkerSettings: [
38 | .linkedLibrary("z")
39 | ]
40 | )
41 | ]
42 | )
43 |
--------------------------------------------------------------------------------
/libxlsxwriter/Readme.md:
--------------------------------------------------------------------------------
1 | # libxlsxwriter
2 |
3 |
4 | Libxlsxwriter: A C library for creating Excel XLSX files.
5 |
6 |
7 | 
8 |
9 |
10 | ## The libxlsxwriter library
11 |
12 | Libxlsxwriter is a C library that can be used to write text, numbers, formulas
13 | and hyperlinks to multiple worksheets in an Excel 2007+ XLSX file.
14 |
15 | It supports features such as:
16 |
17 | - 100% compatible Excel XLSX files.
18 | - Full Excel formatting.
19 | - Merged cells.
20 | - Defined names.
21 | - Autofilters.
22 | - Charts.
23 | - Data validation and drop down lists.
24 | - Conditional formatting.
25 | - Worksheet PNG/JPEG/GIF images.
26 | - Cell comments.
27 | - Support for adding Macros.
28 | - Memory optimization mode for writing large files.
29 | - Source code available on [GitHub](https://github.com/jmcnamara/libxlsxwriter).
30 | - FreeBSD license.
31 | - ANSI C.
32 | - Works with GCC, Clang, Xcode, MSVC 2015, ICC, TCC, MinGW, MingGW-w64/32.
33 | - Works on Linux, FreeBSD, OpenBSD, OS X, iOS and Windows. Also works on MSYS/MSYS2 and Cygwin.
34 | - Compiles for 32 and 64 bit.
35 | - Compiles and works on big and little endian systems.
36 | - The only dependency is on `zlib`.
37 |
38 | Here is an example that was used to create the spreadsheet shown above:
39 |
40 |
41 | ```C
42 | #include "xlsxwriter.h"
43 |
44 | int main() {
45 |
46 | /* Create a new workbook and add a worksheet. */
47 | lxw_workbook *workbook = workbook_new("demo.xlsx");
48 | lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
49 |
50 | /* Add a format. */
51 | lxw_format *format = workbook_add_format(workbook);
52 |
53 | /* Set the bold property for the format */
54 | format_set_bold(format);
55 |
56 | /* Change the column width for clarity. */
57 | worksheet_set_column(worksheet, 0, 0, 20, NULL);
58 |
59 | /* Write some simple text. */
60 | worksheet_write_string(worksheet, 0, 0, "Hello", NULL);
61 |
62 | /* Text with formatting. */
63 | worksheet_write_string(worksheet, 1, 0, "World", format);
64 |
65 | /* Write some numbers. */
66 | worksheet_write_number(worksheet, 2, 0, 123, NULL);
67 | worksheet_write_number(worksheet, 3, 0, 123.456, NULL);
68 |
69 | /* Insert an image. */
70 | worksheet_insert_image(worksheet, 1, 2, "logo.png");
71 |
72 | workbook_close(workbook);
73 |
74 | return 0;
75 | }
76 |
77 | ```
78 |
79 |
80 | See the [full documentation](http://libxlsxwriter.github.io) for the getting
81 | started guide, a tutorial, the main API documentation and examples.
82 |
83 |
--------------------------------------------------------------------------------
/libxlsxwriter/build.zig.zon:
--------------------------------------------------------------------------------
1 | .{
2 | .name = "libxlsxwriter",
3 | .version = "1.1.6",
4 | .dependencies = .{
5 | .zlib = .{
6 | .url = "https://github.com/kassane/zlib/archive/4a99cc2bfa344c969f086fcb8c5873d80448f3e6.tar.gz",
7 | .hash = "12209e851f7e2c6ba2f01de3e11b1771f03e49666065320abd8414aac152bfa75fae",
8 | },
9 | },
10 | }
11 | //syntax tip: zig - anon struct (json-like)
12 |
--------------------------------------------------------------------------------
/libxlsxwriter/cmake/FindMINIZIP.cmake:
--------------------------------------------------------------------------------
1 | # :copyright: (c) 2017 Alex Huszagh.
2 | # :license: FreeBSD, see LICENSE.txt for more details.
3 |
4 | # FindMINIZIP
5 | # -----------
6 | #
7 | # Find MINIZIP include dirs and libraries
8 | #
9 | # Use this module by invoking find_package with the form::
10 | #
11 | # find_package(MINIZIP
12 | # [version] [EXACT] # Minimum or EXACT version e.g. 1.0.6
13 | # [REQUIRED] # Fail with error if MINIZIP is not found
14 | # )
15 | #
16 | # You may also set `MINIZIP_USE_STATIC_LIBS` to prefer static libraries
17 | # to shared ones.
18 | #
19 | # If found, `MINIZIP_FOUND` will be set to true, and `MINIZIP_LIBRARIES`
20 | # and `MINIZIP_INCLUDE_DIRS` will both be set.
21 | #
22 | # You may optionally set `MINIZIP_ROOT` to specify a custom root directory
23 | # for the MINIZIP installation.
24 | #
25 |
26 | include(CheckCXXSourceCompiles)
27 | include(FindPackage)
28 |
29 | # PATHS
30 | # -----
31 |
32 | set(MINIZIP_SEARCH_PATHS)
33 |
34 | if(MINIZIP_ROOT)
35 | list(APPEND MINIZIP_SEARCH_PATHS ${MINIZIP_ROOT})
36 | endif()
37 |
38 | if(WIN32)
39 | list(APPEND ZLIB_SEARCH_PATHS
40 | "$ENV{PROGRAMFILES}/minizip"
41 | )
42 | endif()
43 |
44 | unset(MINIZIP_SYSTEM_ROOT)
45 | unset(MINIZIP_CUSTOM_ROOT)
46 | unset(MINIZIP_SEARCH_HKEY)
47 |
48 | # FIND
49 | # ----
50 |
51 | # INCLUDE DIRECTORY
52 | SetSuffixes(MINIZIP)
53 | foreach(search ${MINIZIP_SEARCH_PATHS})
54 | FIND_PATH(MINIZIP_INCLUDE_DIR
55 | NAMES minizip/zip.h
56 | PATHS ${search}
57 | PATH_SUFFIXES include
58 | )
59 | endforeach(search)
60 |
61 | if(NOT MINIZIP_INCLUDE_DIR)
62 | FIND_PATH(MINIZIP_INCLUDE_DIR minizip/zip.h PATH_SUFFIXES include)
63 | endif()
64 |
65 | # LIBRARY PATHS
66 | set(MINIZIP_LIBRARY_NAMES minizip)
67 | if(CMAKE_BUILD_TYPE MATCHES Debug)
68 | list(APPEND MINIZIP_LIBRARY_NAMES minizipd)
69 | endif()
70 |
71 | foreach(search ${MINIZIP_SEARCH_PATHS})
72 | FIND_LIBRARY(MINIZIP_LIBRARY
73 | NAMES ${MINIZIP_LIBRARY_NAMES}
74 | PATHS ${search}
75 | PATH_SUFFIXES lib
76 | )
77 | endforeach(search)
78 |
79 | if(NOT MINIZIP_LIBRARY)
80 | FIND_LIBRARY(MINIZIP_LIBRARY NAMES ${MINIZIP_LIBRARY_NAMES} PATH_SUFFIXES lib)
81 | endif()
82 |
83 | set(MINIZIP_INCLUDE_DIRS ${MINIZIP_INCLUDE_DIR})
84 | set(MINIZIP_LIBRARIES ${MINIZIP_LIBRARY})
85 |
86 | CheckFound(MINIZIP)
87 | FindStaticLibs(MINIZIP)
88 |
89 | # VERSION
90 | # -------
91 |
92 | if(MINIZIP_FOUND)
93 | file(STRINGS "${MINIZIP_INCLUDE_DIRS}/zlib.h" MINIZIP_VERSION_CONTENTS REGEX "version [0-9]+\\.[0-9]+(\\.[0-9]+)?")
94 | string(REGEX REPLACE ".*version ([0-9]+)\\.[0-9]+" "\\1" MINIZIP_VERSION_MAJOR "${MINIZIP_VERSION_CONTENTS}")
95 | string(REGEX REPLACE ".*version [0-9]+\\.([0-9]+)" "\\1" MINIZIP_VERSION_MINOR "${MINIZIP_VERSION_CONTENTS}")
96 | set(MINIZIP_VERSION_PATCH 0)
97 |
98 | set(MINIZIP_VERSION_STRING "${MINIZIP_VERSION_MAJOR}.${MINIZIP_VERSION_MINOR}.${MINIZIP_VERSION_PATCH}")
99 | set(MINIZIP_VERSION ${MINIZIP_VERSION_STRING})
100 |
101 | MatchVersion(MINIZIP)
102 | endif()
103 |
104 | # COMPILATION
105 | # -----------
106 |
107 | set(MINIZIP_CODE "
108 | #include
109 | int main(void)
110 | {
111 | zip_fileinfo zipfile_info;
112 |
113 | return 0;
114 | }
115 | "
116 | )
117 |
118 | if(MINIZIP_FOUND)
119 | CheckCompiles(MINIZIP)
120 | endif()
121 | RequiredPackageFound(MINIZIP)
122 |
--------------------------------------------------------------------------------
/libxlsxwriter/cmake/FindPackage.cmake:
--------------------------------------------------------------------------------
1 | # :copyright: (c) 2017 Alex Huszagh.
2 | # :license: FreeBSD, see LICENSE.txt for more details.
3 |
4 | # FindPackage
5 | # -----------
6 | #
7 | # Macros and functions to help find packages. Do not invoke this module
8 | # directly, it merely provides library definitions to be invoked
9 | # by other find utilities.
10 |
11 | include(CheckCXXSourceCompiles)
12 |
13 |
14 | # Return if the package name has previously been found
15 | #
16 | # Args:
17 | # packageName Name of the package
18 | #
19 | # Example:
20 | # ReturnFound(Iconv)
21 | #
22 | macro(ReturnFound packageName)
23 | if(${packageName}_FOUND)
24 | return()
25 | endif()
26 | endmacro(ReturnFound)
27 |
28 |
29 | # Set the library extensions for a given package dependent on whether
30 | # to search for static or dynamic libraries.
31 | #
32 | # Args:
33 | # packageName Name of the package
34 | #
35 | # Example:
36 | # SetSuffixes(IConv)
37 | #
38 | macro(SetSuffixes packageName)
39 | if(${packageName}_USE_STATIC_LIBS)
40 | if(MSVC)
41 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
42 | else()
43 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
44 | endif()
45 | else()
46 | if(WIN32)
47 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".dll" ".lib" ".a")
48 | else()
49 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
50 | endif()
51 | endif()
52 | endmacro(SetSuffixes)
53 |
54 |
55 | # Check if the package was found.
56 | #
57 | # Args:
58 | # packageName Name of the package
59 | #
60 | # Example:
61 | # CheckFound(IConv)
62 | #
63 | macro(CheckFound packageName)
64 | if(${packageName}_INCLUDE_DIRS AND ${packageName}_LIBRARIES)
65 | set(${packageName}_FOUND TRUE)
66 | endif()
67 | endmacro(CheckFound)
68 |
69 |
70 | # Replace a dynamic library with a `.dll.a` extension with the corresponding
71 | # library removing the `.dll`.
72 | #
73 | # Args:
74 | # libraryName Variable name for path to found library
75 | #
76 | # Example:
77 | # ReplaceDynamic(/mingw64/lib/libiconv.dll.a)
78 | #
79 | macro(ReplaceDynamic libraryName)
80 | if(${libraryName} MATCHES ".dll.a")
81 | string(REPLACE ".dll.a" ".a" static ${${libraryName}})
82 | if(EXISTS ${static})
83 | set(${libraryName} ${static})
84 | endif()
85 | endif()
86 | endmacro(ReplaceDynamic)
87 |
88 |
89 | # Replace a dynamic libraries with the static variants, with integrity
90 | # checks for the package.
91 | #
92 | # Args:
93 | # packageName Name of the package
94 | #
95 | # Example:
96 | # FindStaticLibs(IConv)
97 | #
98 | macro(FindStaticLibs packageName)
99 | if(${packageName}_USE_STATIC_LIBS AND MSYS)
100 | # convert `.dll.a` to `.a`
101 | set(${packageName}_LIBRARY_SOURCE ${${packageName}_LIBRARIES})
102 | set(${packageName}_LIBRARIES "")
103 | foreach(library ${${packageName}_LIBRARY_SOURCE})
104 | # replace each dynamic library with a single one
105 | set(static_library ${library})
106 | ReplaceDynamic(static_library)
107 | list(APPEND ${packageName}_LIBRARIES ${static_library})
108 | endforeach(library)
109 | endif()
110 | endmacro(FindStaticLibs)
111 |
112 |
113 | # Checks if a suitable version for the found library was identified,
114 | # if provided. The library can either force exact or inexact matching.
115 | #
116 | # Args:
117 | # packageName Name of the package
118 | #
119 | # Example:
120 | # MatchVersion(ICU)
121 | #
122 | macro(MatchVersion packageName)
123 | if(${packageName}_FOUND AND ${packageName}_FIND_VERSION)
124 | # MATCH VERSION
125 | if(${packageName}_FIND_VERSION_EXACT)
126 | # EXACT VERSION
127 | if(${packageName}_FIND_VERSION VERSION_EQUAL ${packageName}_VERSION)
128 | else()
129 | set(${packageName}_FOUND FALSE)
130 | endif()
131 | else()
132 | # GREATER THAN VERSION
133 | if(${packageName}_VERSION VERSION_LESS ${packageName}_FIND_VERSION)
134 | set(${packageName}_FOUND FALSE)
135 | endif()
136 | endif()
137 | endif()
138 | endmacro(MatchVersion)
139 |
140 |
141 | # Check if a sample program compiles, if not, set the library to not found.
142 | #
143 | # Args:
144 | # packageName Name of the package
145 | # code String of simple program depending on the library
146 | #
147 | # Example:
148 | # set(IConv_CODE "int main(int argc, char **argv){ return 0; }")
149 | # CheckCompiles(IConv)
150 | #
151 | macro(CheckCompiles packageName)
152 | # FLAGS
153 | set(CMAKE_REQUIRED_INCLUDES ${${packageName}_INCLUDE_DIRS})
154 | set(CMAKE_REQUIRED_LIBRARIES ${${packageName}_LIBRARIES})
155 |
156 | # COMPILATION
157 | check_cxx_source_compiles("${${packageName}_CODE}" ${packageName}_COMPILES)
158 | if(NOT ${${packageName}_COMPILES})
159 | set(${packageName}_FOUND FALSE)
160 | message(SEND_ERROR "Cannot compile a simple ${packageName} program.")
161 | endif()
162 |
163 | endmacro(CheckCompiles)
164 |
165 |
166 | # Send an error if a required package was not found. Otherwise, if the
167 | # package is found, report to the user it was identified.
168 | #
169 | # Args:
170 | # packageName Name of the package
171 | #
172 | # Example:
173 | # RequiredPackageFound(ICU)
174 | #
175 | macro(RequiredPackageFound packageName)
176 | if(${packageName}_FOUND)
177 | message("Found ${packageName}.")
178 | else()
179 | if(${packageName}_FIND_REQUIRED)
180 | message(SEND_ERROR "Unable to find requested ${packageName} libraries.")
181 | endif()
182 | endif()
183 | endmacro(RequiredPackageFound)
184 |
--------------------------------------------------------------------------------
/libxlsxwriter/cmake/i686-toolchain.cmake:
--------------------------------------------------------------------------------
1 | set(CMAKE_SYSTEM_NAME Linux)
2 | set(CMAKE_SYSTEM_VERSION 1)
3 | set(CMAKE_SYSTEM_PROCESSOR "i686")
4 |
5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32" CACHE STRING "c++ flags")
6 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32" CACHE STRING "c flags")
7 | set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -m32" CACHE STRING "asm flags")
8 |
--------------------------------------------------------------------------------
/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "../xlsxwriter.h"
4 | #import "app.h"
5 | #import "chart.h"
6 | #import "chartsheet.h"
7 | #import "comment.h"
8 | #import "common.h"
9 | #import "content_types.h"
10 | #import "core.h"
11 | #import "custom.h"
12 | #import "drawing.h"
13 | #import "format.h"
14 | #import "hash_table.h"
15 | #import "metadata.h"
16 | #import "packager.h"
17 | #import "relationships.h"
18 | #import "shared_strings.h"
19 | #import "styles.h"
20 | #import "table.h"
21 | #import "theme.h"
22 | #import "third_party/emyg_dtoa.h"
23 | #import "third_party/ioapi.h"
24 | #import "third_party/md5.h"
25 | #import "third_party/queue.h"
26 | #import "third_party/tmpfileplus.h"
27 | #import "third_party/tree.h"
28 | #import "third_party/zip.h"
29 | #import "utility.h"
30 | #import "vml.h"
31 | #import "workbook.h"
32 | #import "worksheet.h"
33 | #import "xmlwriter.h"
34 |
35 | FOUNDATION_EXPORT double xlsxwriterVersionNumber;
36 | FOUNDATION_EXPORT const unsigned char xlsxwriterVersionString[];
37 |
38 |
--------------------------------------------------------------------------------
/libxlsxwriter/cocoapods/libxlsxwriter.modulemap:
--------------------------------------------------------------------------------
1 | framework module xlsxwriter {
2 | umbrella header "xlsxwriter/libxlsxwriter-umbrella.h"
3 | header "xlsxwriter.h"
4 |
5 | export *
6 | module * { export * }
7 | }
8 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | */
6 |
7 | /**
8 | * @file xlsxwriter.h
9 | *
10 | * xlsxwriter - A library for creating Excel XLSX files.
11 | *
12 | */
13 | #ifndef __LXW_XLSXWRITER_H__
14 | #define __LXW_XLSXWRITER_H__
15 |
16 | #include "xlsxwriter/workbook.h"
17 | #include "xlsxwriter/worksheet.h"
18 | #include "xlsxwriter/format.h"
19 | #include "xlsxwriter/utility.h"
20 |
21 | #define LXW_VERSION "1.1.5"
22 | #define LXW_VERSION_ID 115
23 | #define LXW_SOVERSION "5"
24 |
25 | #endif /* __LXW_XLSXWRITER_H__ */
26 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/app.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * app - A libxlsxwriter library for creating Excel XLSX app files.
7 | *
8 | */
9 | #ifndef __LXW_APP_H__
10 | #define __LXW_APP_H__
11 |
12 | #include
13 | #include
14 | #include "workbook.h"
15 | #include "common.h"
16 |
17 | /* Define the queue.h TAILQ structs for the App structs. */
18 | STAILQ_HEAD(lxw_heading_pairs, lxw_heading_pair);
19 | STAILQ_HEAD(lxw_part_names, lxw_part_name);
20 |
21 | typedef struct lxw_heading_pair {
22 |
23 | char *key;
24 | char *value;
25 |
26 | STAILQ_ENTRY (lxw_heading_pair) list_pointers;
27 |
28 | } lxw_heading_pair;
29 |
30 | typedef struct lxw_part_name {
31 |
32 | char *name;
33 |
34 | STAILQ_ENTRY (lxw_part_name) list_pointers;
35 |
36 | } lxw_part_name;
37 |
38 | /* Struct to represent an App object. */
39 | typedef struct lxw_app {
40 |
41 | FILE *file;
42 |
43 | struct lxw_heading_pairs *heading_pairs;
44 | struct lxw_part_names *part_names;
45 | lxw_doc_properties *properties;
46 |
47 | uint32_t num_heading_pairs;
48 | uint32_t num_part_names;
49 | uint8_t doc_security;
50 |
51 | } lxw_app;
52 |
53 |
54 | /* *INDENT-OFF* */
55 | #ifdef __cplusplus
56 | extern "C" {
57 | #endif
58 | /* *INDENT-ON* */
59 |
60 | lxw_app *lxw_app_new(void);
61 | void lxw_app_free(lxw_app *app);
62 | void lxw_app_assemble_xml_file(lxw_app *self);
63 | void lxw_app_add_part_name(lxw_app *self, const char *name);
64 | void lxw_app_add_heading_pair(lxw_app *self, const char *key,
65 | const char *value);
66 |
67 | /* Declarations required for unit testing. */
68 | #ifdef TESTING
69 |
70 | STATIC void _app_xml_declaration(lxw_app *self);
71 |
72 | #endif /* TESTING */
73 |
74 | /* *INDENT-OFF* */
75 | #ifdef __cplusplus
76 | }
77 | #endif
78 | /* *INDENT-ON* */
79 |
80 | #endif /* __LXW_APP_H__ */
81 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/comment.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * comment - A libxlsxwriter library for creating Excel XLSX comment files.
7 | *
8 | */
9 | #ifndef __LXW_COMMENT_H__
10 | #define __LXW_COMMENT_H__
11 |
12 | #include
13 |
14 | #include "common.h"
15 | #include "worksheet.h"
16 |
17 | /* Define the tree.h RB structs for the red-black head types. */
18 | RB_HEAD(lxw_author_ids, lxw_author_id);
19 |
20 | /*
21 | * Struct to represent a comment object.
22 | */
23 | typedef struct lxw_comment {
24 |
25 | FILE *file;
26 | struct lxw_comment_objs *comment_objs;
27 | struct lxw_author_ids *author_ids;
28 | char *comment_author;
29 | uint32_t author_id;
30 |
31 | } lxw_comment;
32 |
33 | /* Struct to an author id */
34 | typedef struct lxw_author_id {
35 | uint32_t id;
36 | char *author;
37 |
38 | RB_ENTRY (lxw_author_id) tree_pointers;
39 | } lxw_author_id;
40 |
41 | #define LXW_RB_GENERATE_AUTHOR_IDS(name, type, field, cmp) \
42 | RB_GENERATE_INSERT_COLOR(name, type, field, static) \
43 | RB_GENERATE_REMOVE_COLOR(name, type, field, static) \
44 | RB_GENERATE_INSERT(name, type, field, cmp, static) \
45 | RB_GENERATE_REMOVE(name, type, field, static) \
46 | RB_GENERATE_FIND(name, type, field, cmp, static) \
47 | RB_GENERATE_NEXT(name, type, field, static) \
48 | RB_GENERATE_MINMAX(name, type, field, static) \
49 | /* Add unused struct to allow adding a semicolon */ \
50 | struct lxw_rb_generate_author_ids{int unused;}
51 |
52 |
53 | /* *INDENT-OFF* */
54 | #ifdef __cplusplus
55 | extern "C" {
56 | #endif
57 | /* *INDENT-ON* */
58 |
59 | lxw_comment *lxw_comment_new(void);
60 | void lxw_comment_free(lxw_comment *comment);
61 | void lxw_comment_assemble_xml_file(lxw_comment *self);
62 |
63 | /* Declarations required for unit testing. */
64 | #ifdef TESTING
65 |
66 | STATIC void _comment_xml_declaration(lxw_comment *self);
67 |
68 | #endif /* TESTING */
69 |
70 | /* *INDENT-OFF* */
71 | #ifdef __cplusplus
72 | }
73 | #endif
74 | /* *INDENT-ON* */
75 |
76 | #endif /* __LXW_COMMENT_H__ */
77 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/content_types.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * content_types - A libxlsxwriter library for creating Excel XLSX
7 | * content_types files.
8 | *
9 | */
10 | #ifndef __LXW_CONTENT_TYPES_H__
11 | #define __LXW_CONTENT_TYPES_H__
12 |
13 | #include
14 | #include
15 |
16 | #include "common.h"
17 |
18 | #define LXW_APP_PACKAGE "application/vnd.openxmlformats-package."
19 | #define LXW_APP_DOCUMENT "application/vnd.openxmlformats-officedocument."
20 | #define LXW_APP_MSEXCEL "application/vnd.ms-excel."
21 |
22 | /*
23 | * Struct to represent a content_types.
24 | */
25 | typedef struct lxw_content_types {
26 |
27 | FILE *file;
28 |
29 | struct lxw_tuples *default_types;
30 | struct lxw_tuples *overrides;
31 |
32 | } lxw_content_types;
33 |
34 |
35 | /* *INDENT-OFF* */
36 | #ifdef __cplusplus
37 | extern "C" {
38 | #endif
39 | /* *INDENT-ON* */
40 |
41 | lxw_content_types *lxw_content_types_new(void);
42 | void lxw_content_types_free(lxw_content_types *content_types);
43 | void lxw_content_types_assemble_xml_file(lxw_content_types *content_types);
44 | void lxw_ct_add_default(lxw_content_types *content_types, const char *key,
45 | const char *value);
46 | void lxw_ct_add_override(lxw_content_types *content_types, const char *key,
47 | const char *value);
48 | void lxw_ct_add_worksheet_name(lxw_content_types *content_types,
49 | const char *name);
50 | void lxw_ct_add_chartsheet_name(lxw_content_types *content_types,
51 | const char *name);
52 | void lxw_ct_add_chart_name(lxw_content_types *content_types,
53 | const char *name);
54 | void lxw_ct_add_drawing_name(lxw_content_types *content_types,
55 | const char *name);
56 | void lxw_ct_add_table_name(lxw_content_types *content_types,
57 | const char *name);
58 | void lxw_ct_add_comment_name(lxw_content_types *content_types,
59 | const char *name);
60 | void lxw_ct_add_vml_name(lxw_content_types *content_types);
61 |
62 | void lxw_ct_add_shared_strings(lxw_content_types *content_types);
63 | void lxw_ct_add_calc_chain(lxw_content_types *content_types);
64 | void lxw_ct_add_custom_properties(lxw_content_types *content_types);
65 | void lxw_ct_add_metadata(lxw_content_types *content_types);
66 |
67 | /* Declarations required for unit testing. */
68 | #ifdef TESTING
69 |
70 | STATIC void _content_types_xml_declaration(lxw_content_types *self);
71 | STATIC void _write_default(lxw_content_types *self, const char *ext,
72 | const char *type);
73 | STATIC void _write_override(lxw_content_types *self, const char *part_name,
74 | const char *type);
75 |
76 | #endif /* TESTING */
77 |
78 | /* *INDENT-OFF* */
79 | #ifdef __cplusplus
80 | }
81 | #endif
82 | /* *INDENT-ON* */
83 |
84 | #endif /* __LXW_CONTENT_TYPES_H__ */
85 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/core.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * core - A libxlsxwriter library for creating Excel XLSX core files.
7 | *
8 | */
9 | #ifndef __LXW_CORE_H__
10 | #define __LXW_CORE_H__
11 |
12 | #include
13 |
14 | #include "workbook.h"
15 | #include "common.h"
16 |
17 | /*
18 | * Struct to represent a core.
19 | */
20 | typedef struct lxw_core {
21 |
22 | FILE *file;
23 | lxw_doc_properties *properties;
24 |
25 | } lxw_core;
26 |
27 |
28 | /* *INDENT-OFF* */
29 | #ifdef __cplusplus
30 | extern "C" {
31 | #endif
32 | /* *INDENT-ON* */
33 |
34 | lxw_core *lxw_core_new(void);
35 | void lxw_core_free(lxw_core *core);
36 | void lxw_core_assemble_xml_file(lxw_core *self);
37 |
38 | /* Declarations required for unit testing. */
39 | #ifdef TESTING
40 |
41 | STATIC void _core_xml_declaration(lxw_core *self);
42 |
43 | #endif /* TESTING */
44 |
45 | /* *INDENT-OFF* */
46 | #ifdef __cplusplus
47 | }
48 | #endif
49 | /* *INDENT-ON* */
50 |
51 | #endif /* __LXW_CORE_H__ */
52 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/custom.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * custom - A libxlsxwriter library for creating Excel custom property files.
7 | *
8 | */
9 | #ifndef __LXW_CUSTOM_H__
10 | #define __LXW_CUSTOM_H__
11 |
12 | #include
13 |
14 | #include "common.h"
15 |
16 | /*
17 | * Struct to represent a custom property file object.
18 | */
19 | typedef struct lxw_custom {
20 |
21 | FILE *file;
22 |
23 | struct lxw_custom_properties *custom_properties;
24 | uint32_t pid;
25 |
26 | } lxw_custom;
27 |
28 |
29 | /* *INDENT-OFF* */
30 | #ifdef __cplusplus
31 | extern "C" {
32 | #endif
33 | /* *INDENT-ON* */
34 |
35 | lxw_custom *lxw_custom_new(void);
36 | void lxw_custom_free(lxw_custom *custom);
37 | void lxw_custom_assemble_xml_file(lxw_custom *self);
38 |
39 | /* Declarations required for unit testing. */
40 | #ifdef TESTING
41 |
42 | STATIC void _custom_xml_declaration(lxw_custom *self);
43 |
44 | #endif /* TESTING */
45 |
46 | /* *INDENT-OFF* */
47 | #ifdef __cplusplus
48 | }
49 | #endif
50 | /* *INDENT-ON* */
51 |
52 | #endif /* __LXW_CUSTOM_H__ */
53 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/drawing.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * drawing - A libxlsxwriter library for creating Excel XLSX drawing files.
7 | *
8 | */
9 | #ifndef __LXW_DRAWING_H__
10 | #define __LXW_DRAWING_H__
11 |
12 | #include
13 | #include
14 |
15 | #include "common.h"
16 |
17 | STAILQ_HEAD(lxw_drawing_objects, lxw_drawing_object);
18 |
19 | enum lxw_drawing_types {
20 | LXW_DRAWING_NONE = 0,
21 | LXW_DRAWING_IMAGE,
22 | LXW_DRAWING_CHART,
23 | LXW_DRAWING_SHAPE
24 | };
25 |
26 | enum image_types {
27 | LXW_IMAGE_UNKNOWN = 0,
28 | LXW_IMAGE_PNG,
29 | LXW_IMAGE_JPEG,
30 | LXW_IMAGE_BMP,
31 | LXW_IMAGE_GIF
32 | };
33 |
34 | /* Coordinates used in a drawing object. */
35 | typedef struct lxw_drawing_coords {
36 | uint32_t col;
37 | uint32_t row;
38 | double col_offset;
39 | double row_offset;
40 | } lxw_drawing_coords;
41 |
42 | /* Object to represent the properties of a drawing. */
43 | typedef struct lxw_drawing_object {
44 | uint8_t type;
45 | uint8_t anchor;
46 | struct lxw_drawing_coords from;
47 | struct lxw_drawing_coords to;
48 | uint64_t col_absolute;
49 | uint64_t row_absolute;
50 | uint32_t width;
51 | uint32_t height;
52 | uint8_t shape;
53 | uint32_t rel_index;
54 | uint32_t url_rel_index;
55 | char *description;
56 | char *tip;
57 | uint8_t decorative;
58 |
59 | STAILQ_ENTRY (lxw_drawing_object) list_pointers;
60 |
61 | } lxw_drawing_object;
62 |
63 | /*
64 | * Struct to represent a collection of drawings.
65 | */
66 | typedef struct lxw_drawing {
67 |
68 | FILE *file;
69 |
70 | uint8_t embedded;
71 | uint8_t orientation;
72 |
73 | struct lxw_drawing_objects *drawing_objects;
74 |
75 | } lxw_drawing;
76 |
77 |
78 | /* *INDENT-OFF* */
79 | #ifdef __cplusplus
80 | extern "C" {
81 | #endif
82 | /* *INDENT-ON* */
83 |
84 | lxw_drawing *lxw_drawing_new(void);
85 | void lxw_drawing_free(lxw_drawing *drawing);
86 | void lxw_drawing_assemble_xml_file(lxw_drawing *self);
87 | void lxw_free_drawing_object(struct lxw_drawing_object *drawing_object);
88 | void lxw_add_drawing_object(lxw_drawing *drawing,
89 | lxw_drawing_object *drawing_object);
90 |
91 | /* Declarations required for unit testing. */
92 | #ifdef TESTING
93 |
94 | STATIC void _drawing_xml_declaration(lxw_drawing *self);
95 | #endif /* TESTING */
96 |
97 | /* *INDENT-OFF* */
98 | #ifdef __cplusplus
99 | }
100 | #endif
101 | /* *INDENT-ON* */
102 |
103 | #endif /* __LXW_DRAWING_H__ */
104 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/hash_table.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * hash_table - Hash table functions for libxlsxwriter.
7 | *
8 | */
9 |
10 | #ifndef __LXW_HASH_TABLE_H__
11 | #define __LXW_HASH_TABLE_H__
12 |
13 | #include "common.h"
14 |
15 | /* Macro to loop over hash table elements in insertion order. */
16 | #define LXW_FOREACH_ORDERED(elem, hash_table) \
17 | STAILQ_FOREACH((elem), (hash_table)->order_list, lxw_hash_order_pointers)
18 |
19 | /* List declarations. */
20 | STAILQ_HEAD(lxw_hash_order_list, lxw_hash_element);
21 | SLIST_HEAD(lxw_hash_bucket_list, lxw_hash_element);
22 |
23 | /* LXW_HASH hash table struct. */
24 | typedef struct lxw_hash_table {
25 | uint32_t num_buckets;
26 | uint32_t used_buckets;
27 | uint32_t unique_count;
28 | uint8_t free_key;
29 | uint8_t free_value;
30 |
31 | struct lxw_hash_order_list *order_list;
32 | struct lxw_hash_bucket_list **buckets;
33 | } lxw_hash_table;
34 |
35 | /*
36 | * LXW_HASH table element struct.
37 | *
38 | * The hash elements contain pointers to allow them to be stored in
39 | * lists in the the hash table buckets and also pointers to track the
40 | * insertion order in a separate list.
41 | */
42 | typedef struct lxw_hash_element {
43 | void *key;
44 | void *value;
45 |
46 | STAILQ_ENTRY (lxw_hash_element) lxw_hash_order_pointers;
47 | SLIST_ENTRY (lxw_hash_element) lxw_hash_list_pointers;
48 | } lxw_hash_element;
49 |
50 |
51 | /* *INDENT-OFF* */
52 | #ifdef __cplusplus
53 | extern "C" {
54 | #endif
55 | /* *INDENT-ON* */
56 |
57 | lxw_hash_element *lxw_hash_key_exists(lxw_hash_table *lxw_hash, void *key,
58 | size_t key_len);
59 | lxw_hash_element *lxw_insert_hash_element(lxw_hash_table *lxw_hash, void *key,
60 | void *value, size_t key_len);
61 | lxw_hash_table *lxw_hash_new(uint32_t num_buckets, uint8_t free_key,
62 | uint8_t free_value);
63 | void lxw_hash_free(lxw_hash_table *lxw_hash);
64 |
65 | /* Declarations required for unit testing. */
66 | #ifdef TESTING
67 |
68 | #endif
69 |
70 | /* *INDENT-OFF* */
71 | #ifdef __cplusplus
72 | }
73 | #endif
74 | /* *INDENT-ON* */
75 |
76 | #endif /* __LXW_HASH_TABLE_H__ */
77 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/metadata.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * metadata - A libxlsxwriter library for creating Excel XLSX metadata files.
7 | *
8 | */
9 | #ifndef __LXW_METADATA_H__
10 | #define __LXW_METADATA_H__
11 |
12 | #include
13 |
14 | #include "common.h"
15 |
16 | /*
17 | * Struct to represent a metadata object.
18 | */
19 | typedef struct lxw_metadata {
20 |
21 | FILE *file;
22 |
23 | } lxw_metadata;
24 |
25 |
26 | /* *INDENT-OFF* */
27 | #ifdef __cplusplus
28 | extern "C" {
29 | #endif
30 | /* *INDENT-ON* */
31 |
32 | lxw_metadata *lxw_metadata_new(void);
33 | void lxw_metadata_free(lxw_metadata *metadata);
34 | void lxw_metadata_assemble_xml_file(lxw_metadata *self);
35 |
36 | /* Declarations required for unit testing. */
37 | #ifdef TESTING
38 |
39 | STATIC void _metadata_xml_declaration(lxw_metadata *self);
40 |
41 | #endif /* TESTING */
42 |
43 | /* *INDENT-OFF* */
44 | #ifdef __cplusplus
45 | }
46 | #endif
47 | /* *INDENT-ON* */
48 |
49 | #endif /* __LXW_METADATA_H__ */
50 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/packager.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * packager - A libxlsxwriter library for creating Excel XLSX packager files.
7 | *
8 | */
9 | #ifndef __LXW_PACKAGER_H__
10 | #define __LXW_PACKAGER_H__
11 |
12 | #include
13 |
14 | #ifdef USE_SYSTEM_MINIZIP
15 | #ifdef __GNUC__
16 | #pragma GCC system_header
17 | #endif
18 | #include "minizip/zip.h"
19 | #else
20 | #include "third_party/zip.h"
21 | #endif
22 |
23 | #include "common.h"
24 | #include "workbook.h"
25 | #include "worksheet.h"
26 | #include "shared_strings.h"
27 | #include "app.h"
28 | #include "core.h"
29 | #include "custom.h"
30 | #include "table.h"
31 | #include "theme.h"
32 | #include "styles.h"
33 | #include "format.h"
34 | #include "content_types.h"
35 | #include "relationships.h"
36 | #include "vml.h"
37 | #include "comment.h"
38 | #include "metadata.h"
39 |
40 | #define LXW_ZIP_BUFFER_SIZE (16384)
41 |
42 | /* If zip returns a ZIP_XXX error then errno is set and we can trap that in
43 | * workbook.c. Otherwise return a default libxlsxwriter error. */
44 | #define RETURN_ON_ZIP_ERROR(err, default_err) \
45 | do { \
46 | if (err == ZIP_ERRNO) \
47 | return LXW_ERROR_ZIP_FILE_OPERATION; \
48 | else if (err == ZIP_PARAMERROR) \
49 | return LXW_ERROR_ZIP_PARAMETER_ERROR; \
50 | else if (err == ZIP_BADZIPFILE) \
51 | return LXW_ERROR_ZIP_BAD_ZIP_FILE; \
52 | else if (err == ZIP_INTERNALERROR) \
53 | return LXW_ERROR_ZIP_INTERNAL_ERROR; \
54 | else \
55 | return default_err; \
56 | } while (0)
57 |
58 | /*
59 | * Struct to represent a packager.
60 | */
61 | typedef struct lxw_packager {
62 |
63 | FILE *file;
64 | lxw_workbook *workbook;
65 |
66 | size_t buffer_size;
67 | size_t output_buffer_size;
68 | zipFile zipfile;
69 | zip_fileinfo zipfile_info;
70 | const char *filename;
71 | const char *buffer;
72 | char *output_buffer;
73 | const char *tmpdir;
74 | uint8_t use_zip64;
75 |
76 | } lxw_packager;
77 |
78 |
79 | /* *INDENT-OFF* */
80 | #ifdef __cplusplus
81 | extern "C" {
82 | #endif
83 | /* *INDENT-ON* */
84 |
85 | lxw_packager *lxw_packager_new(const char *filename, const char *tmpdir,
86 | uint8_t use_zip64);
87 | void lxw_packager_free(lxw_packager *packager);
88 | lxw_error lxw_create_package(lxw_packager *self);
89 |
90 | /* Declarations required for unit testing. */
91 | #ifdef TESTING
92 |
93 | #endif /* TESTING */
94 |
95 | /* *INDENT-OFF* */
96 | #ifdef __cplusplus
97 | }
98 | #endif
99 | /* *INDENT-ON* */
100 |
101 | #endif /* __LXW_PACKAGER_H__ */
102 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/relationships.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * relationships - A libxlsxwriter library for creating Excel XLSX
7 | * relationships files.
8 | *
9 | */
10 | #ifndef __LXW_RELATIONSHIPS_H__
11 | #define __LXW_RELATIONSHIPS_H__
12 |
13 | #include
14 |
15 | #include "common.h"
16 |
17 | /* Define the queue.h STAILQ structs for the generic data structs. */
18 | STAILQ_HEAD(lxw_rel_tuples, lxw_rel_tuple);
19 |
20 | typedef struct lxw_rel_tuple {
21 |
22 | char *type;
23 | char *target;
24 | char *target_mode;
25 |
26 | STAILQ_ENTRY (lxw_rel_tuple) list_pointers;
27 |
28 | } lxw_rel_tuple;
29 |
30 | /*
31 | * Struct to represent a relationships.
32 | */
33 | typedef struct lxw_relationships {
34 |
35 | FILE *file;
36 |
37 | uint32_t rel_id;
38 | struct lxw_rel_tuples *relationships;
39 |
40 | } lxw_relationships;
41 |
42 |
43 |
44 | /* *INDENT-OFF* */
45 | #ifdef __cplusplus
46 | extern "C" {
47 | #endif
48 | /* *INDENT-ON* */
49 |
50 | lxw_relationships *lxw_relationships_new(void);
51 | void lxw_free_relationships(lxw_relationships *relationships);
52 | void lxw_relationships_assemble_xml_file(lxw_relationships *self);
53 |
54 | void lxw_add_document_relationship(lxw_relationships *self, const char *type,
55 | const char *target);
56 | void lxw_add_package_relationship(lxw_relationships *self, const char *type,
57 | const char *target);
58 | void lxw_add_ms_package_relationship(lxw_relationships *self,
59 | const char *type, const char *target);
60 | void lxw_add_worksheet_relationship(lxw_relationships *self, const char *type,
61 | const char *target,
62 | const char *target_mode);
63 |
64 | /* Declarations required for unit testing. */
65 | #ifdef TESTING
66 |
67 | STATIC void _relationships_xml_declaration(lxw_relationships *self);
68 |
69 | #endif /* TESTING */
70 |
71 | /* *INDENT-OFF* */
72 | #ifdef __cplusplus
73 | }
74 | #endif
75 | /* *INDENT-ON* */
76 |
77 | #endif /* __LXW_RELATIONSHIPS_H__ */
78 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/shared_strings.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * shared_strings - A libxlsxwriter library for creating Excel XLSX
7 | * sst files.
8 | *
9 | */
10 | #ifndef __LXW_SST_H__
11 | #define __LXW_SST_H__
12 |
13 | #include
14 | #include
15 |
16 | #include "common.h"
17 |
18 | /* Define a tree.h RB structure for storing shared strings. */
19 | RB_HEAD(sst_rb_tree, sst_element);
20 |
21 | /* Define a queue.h structure for storing shared strings in insertion order. */
22 | STAILQ_HEAD(sst_order_list, sst_element);
23 |
24 | /* Wrapper around RB_GENERATE_STATIC from tree.h to avoid unused function
25 | * warnings and to avoid portability issues with the _unused attribute. */
26 | #define LXW_RB_GENERATE_ELEMENT(name, type, field, cmp) \
27 | RB_GENERATE_INSERT_COLOR(name, type, field, static) \
28 | RB_GENERATE_INSERT(name, type, field, cmp, static) \
29 | /* Add unused struct to allow adding a semicolon */ \
30 | struct lxw_rb_generate_element{int unused;}
31 |
32 | /*
33 | * Elements of the SST table. They contain pointers to allow them to
34 | * be stored in a RB tree and also pointers to track the insertion order
35 | * in a separate list.
36 | */
37 | struct sst_element {
38 | uint32_t index;
39 | char *string;
40 | uint8_t is_rich_string;
41 |
42 | STAILQ_ENTRY (sst_element) sst_order_pointers;
43 | RB_ENTRY (sst_element) sst_tree_pointers;
44 | };
45 |
46 | /*
47 | * Struct to represent a sst.
48 | */
49 | typedef struct lxw_sst {
50 | FILE *file;
51 |
52 | uint32_t string_count;
53 | uint32_t unique_count;
54 |
55 | struct sst_order_list *order_list;
56 | struct sst_rb_tree *rb_tree;
57 |
58 | } lxw_sst;
59 |
60 | /* *INDENT-OFF* */
61 | #ifdef __cplusplus
62 | extern "C" {
63 | #endif
64 | /* *INDENT-ON* */
65 |
66 | lxw_sst *lxw_sst_new(void);
67 | void lxw_sst_free(lxw_sst *sst);
68 | struct sst_element *lxw_get_sst_index(lxw_sst *sst, const char *string,
69 | uint8_t is_rich_string);
70 | void lxw_sst_assemble_xml_file(lxw_sst *self);
71 |
72 | /* Declarations required for unit testing. */
73 | #ifdef TESTING
74 |
75 | STATIC void _sst_xml_declaration(lxw_sst *self);
76 |
77 | #endif /* TESTING */
78 |
79 | /* *INDENT-OFF* */
80 | #ifdef __cplusplus
81 | }
82 | #endif
83 | /* *INDENT-ON* */
84 |
85 | #endif /* __LXW_SST_H__ */
86 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/styles.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * styles - A libxlsxwriter library for creating Excel XLSX styles files.
7 | *
8 | */
9 | #ifndef __LXW_STYLES_H__
10 | #define __LXW_STYLES_H__
11 |
12 | #include
13 | #include
14 |
15 | #include "format.h"
16 |
17 | /*
18 | * Struct to represent a styles.
19 | */
20 | typedef struct lxw_styles {
21 |
22 | FILE *file;
23 | uint32_t font_count;
24 | uint32_t xf_count;
25 | uint32_t dxf_count;
26 | uint32_t num_format_count;
27 | uint32_t border_count;
28 | uint32_t fill_count;
29 | struct lxw_formats *xf_formats;
30 | struct lxw_formats *dxf_formats;
31 | uint8_t has_hyperlink;
32 | uint16_t hyperlink_font_id;
33 | uint8_t has_comments;
34 |
35 | } lxw_styles;
36 |
37 |
38 | /* *INDENT-OFF* */
39 | #ifdef __cplusplus
40 | extern "C" {
41 | #endif
42 | /* *INDENT-ON* */
43 |
44 | lxw_styles *lxw_styles_new(void);
45 | void lxw_styles_free(lxw_styles *styles);
46 | void lxw_styles_assemble_xml_file(lxw_styles *self);
47 | void lxw_styles_write_string_fragment(lxw_styles *self, const char *string);
48 | void lxw_styles_write_rich_font(lxw_styles *styles, lxw_format *format);
49 |
50 | /* Declarations required for unit testing. */
51 | #ifdef TESTING
52 |
53 | STATIC void _styles_xml_declaration(lxw_styles *self);
54 | STATIC void _write_style_sheet(lxw_styles *self);
55 | STATIC void _write_font_size(lxw_styles *self, double font_size);
56 | STATIC void _write_font_color_theme(lxw_styles *self, uint8_t theme);
57 | STATIC void _write_font_name(lxw_styles *self, const char *font_name,
58 | uint8_t is_rich_string);
59 | STATIC void _write_font_family(lxw_styles *self, uint8_t font_family);
60 | STATIC void _write_font_scheme(lxw_styles *self, const char *font_scheme);
61 | STATIC void _write_font(lxw_styles *self, lxw_format *format, uint8_t is_dxf,
62 | uint8_t is_rich_string);
63 | STATIC void _write_fonts(lxw_styles *self);
64 | STATIC void _write_default_fill(lxw_styles *self, const char *pattern);
65 | STATIC void _write_fills(lxw_styles *self);
66 | STATIC void _write_border(lxw_styles *self, lxw_format *format,
67 | uint8_t is_dxf);
68 | STATIC void _write_borders(lxw_styles *self);
69 | STATIC void _write_style_xf(lxw_styles *self, uint8_t has_hyperlink,
70 | uint16_t font_id);
71 | STATIC void _write_cell_style_xfs(lxw_styles *self);
72 | STATIC void _write_xf(lxw_styles *self, lxw_format *format);
73 | STATIC void _write_cell_xfs(lxw_styles *self);
74 | STATIC void _write_cell_style(lxw_styles *self, char *name, uint8_t xf_id,
75 | uint8_t builtin_id);
76 | STATIC void _write_cell_styles(lxw_styles *self);
77 | STATIC void _write_dxfs(lxw_styles *self);
78 | STATIC void _write_table_styles(lxw_styles *self);
79 |
80 | #endif /* TESTING */
81 |
82 | /* *INDENT-OFF* */
83 | #ifdef __cplusplus
84 | }
85 | #endif
86 | /* *INDENT-ON* */
87 |
88 | #endif /* __LXW_STYLES_H__ */
89 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/table.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * table - A libxlsxwriter library for creating Excel XLSX table files.
7 | *
8 | */
9 | #ifndef __LXW_TABLE_H__
10 | #define __LXW_TABLE_H__
11 |
12 | #include
13 |
14 | #include "common.h"
15 |
16 | /*
17 | * Struct to represent a table object.
18 | */
19 | typedef struct lxw_table {
20 |
21 | FILE *file;
22 |
23 | struct lxw_table_obj *table_obj;
24 |
25 | } lxw_table;
26 |
27 |
28 | /* *INDENT-OFF* */
29 | #ifdef __cplusplus
30 | extern "C" {
31 | #endif
32 | /* *INDENT-ON* */
33 |
34 | lxw_table *lxw_table_new(void);
35 | void lxw_table_free(lxw_table *table);
36 | void lxw_table_assemble_xml_file(lxw_table *self);
37 |
38 | /* Declarations required for unit testing. */
39 | #ifdef TESTING
40 |
41 | STATIC void _table_xml_declaration(lxw_table *self);
42 |
43 | #endif /* TESTING */
44 |
45 | /* *INDENT-OFF* */
46 | #ifdef __cplusplus
47 | }
48 | #endif
49 | /* *INDENT-ON* */
50 |
51 | #endif /* __LXW_TABLE_H__ */
52 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/theme.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * theme - A libxlsxwriter library for creating Excel XLSX theme files.
7 | *
8 | */
9 | #ifndef __LXW_THEME_H__
10 | #define __LXW_THEME_H__
11 |
12 | #include
13 |
14 | #include "common.h"
15 |
16 | /*
17 | * Struct to represent a theme.
18 | */
19 | typedef struct lxw_theme {
20 |
21 | FILE *file;
22 | } lxw_theme;
23 |
24 |
25 | /* *INDENT-OFF* */
26 | #ifdef __cplusplus
27 | extern "C" {
28 | #endif
29 | /* *INDENT-ON* */
30 |
31 | lxw_theme *lxw_theme_new(void);
32 | void lxw_theme_free(lxw_theme *theme);
33 | void lxw_theme_xml_declaration(lxw_theme *self);
34 | void lxw_theme_assemble_xml_file(lxw_theme *self);
35 |
36 | /* Declarations required for unit testing. */
37 | #ifdef TESTING
38 |
39 | #endif /* TESTING */
40 |
41 | /* *INDENT-OFF* */
42 | #ifdef __cplusplus
43 | }
44 | #endif
45 | /* *INDENT-ON* */
46 |
47 | #endif /* __LXW_THEME_H__ */
48 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/third_party/emyg_dtoa.h:
--------------------------------------------------------------------------------
1 | /* emyg_dtoa.h
2 | ** Copyright (C) 2015 Doug Currie
3 | ** based on dtoa_milo.h
4 | ** Copyright (C) 2014 Milo Yip
5 | **
6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy
7 | ** of this software and associated documentation files (the "Software"), to deal
8 | ** in the Software without restriction, including without limitation the rights
9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | ** copies of the Software, and to permit persons to whom the Software is
11 | ** furnished to do so, subject to the following conditions:
12 | **
13 | ** The above copyright notice and this permission notice shall be included in
14 | ** all copies or substantial portions of the Software.
15 | **
16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | ** THE SOFTWARE.
23 | */
24 |
25 | /* Source from https://github.com/miloyip/dtoa-benchmark */
26 | void emyg_dtoa (double value, char* buffer);
27 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/third_party/md5.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
3 | * MD5 Message-Digest Algorithm (RFC 1321).
4 | *
5 | * Homepage:
6 | * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
7 | *
8 | * Author:
9 | * Alexander Peslyak, better known as Solar Designer
10 | *
11 | * This software was written by Alexander Peslyak in 2001. No copyright is
12 | * claimed, and the software is hereby placed in the public domain.
13 | * In case this attempt to disclaim copyright and place the software in the
14 | * public domain is deemed null and void, then the software is
15 | * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
16 | * general public under the following terms:
17 | *
18 | * Redistribution and use in source and binary forms, with or without
19 | * modification, are permitted.
20 | *
21 | * There's ABSOLUTELY NO WARRANTY, express or implied.
22 | *
23 | * See md5.c for more information.
24 | */
25 |
26 | #ifdef HAVE_OPENSSL
27 | #include
28 | #elif !defined(_MD5_H)
29 | #define _MD5_H
30 |
31 | /* Any 32-bit or wider unsigned integer data type will do */
32 | typedef unsigned int MD5_u32plus;
33 |
34 | typedef struct {
35 | MD5_u32plus lo, hi;
36 | MD5_u32plus a, b, c, d;
37 | unsigned char buffer[64];
38 | MD5_u32plus block[16];
39 | } MD5_CTX;
40 |
41 | extern void MD5_Init(MD5_CTX *ctx);
42 | extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
43 | extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/third_party/tmpfileplus.h:
--------------------------------------------------------------------------------
1 | /* $Id: tmpfileplus.h $ */
2 | /*
3 | * $Date: 2016-06-01 03:31Z $
4 | * $Revision: 2.0.0 $
5 | * $Author: dai $
6 | */
7 |
8 | /*
9 | * This Source Code Form is subject to the terms of the Mozilla Public
10 | * License, v. 2.0. If a copy of the MPL was not distributed with this
11 | * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 | *
13 | * Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd
14 | * .
15 | */
16 |
17 | #if _MSC_VER > 1000
18 | #pragma once
19 | #endif
20 |
21 | #ifndef TMPFILEPLUS_H_
22 | #define TMPFILEPLUS_H_
23 |
24 | #include
25 |
26 | /** Create a unique temporary file.
27 | @param dir (optional) directory to create file. If NULL use default TMP directory.
28 | @param prefix (optional) prefix for file name. If NULL use "tmp.".
29 | @param pathname (optional) pointer to a buffer to receive the temp filename.
30 | Allocated using `malloc()`; user to free. Ignored if NULL.
31 | @param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing.
32 | Otherwise file is automatically deleted when closed.
33 | @return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error.
34 | @exception ENOMEM Not enough memory to allocate filename.
35 | */
36 | FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep);
37 |
38 |
39 | /** Create a unique temporary file with filename stored in a fixed-length buffer.
40 | @param dir (optional) directory to create file. If NULL use default directory.
41 | @param prefix (optional) prefix for file name. If NULL use "tmp.".
42 | @param pathnamebuf (optional) buffer to receive full pathname of temporary file. Ignored if NULL.
43 | @param pathsize Size of buffer to receive filename and its terminating null character.
44 | @param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing.
45 | Otherwise file is automatically deleted when closed.
46 | @return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error.
47 | @exception E2BIG Resulting filename is too big for the buffer `pathnamebuf`.
48 | */
49 | FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep);
50 |
51 | #define TMPFILE_KEEP 1
52 |
53 | #endif /* end TMPFILEPLUS_H_ */
54 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/vml.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * vml - A libxlsxwriter library for creating Excel XLSX vml files.
7 | *
8 | */
9 | #ifndef __LXW_VML_H__
10 | #define __LXW_VML_H__
11 |
12 | #include
13 |
14 | #include "common.h"
15 | #include "worksheet.h"
16 |
17 | /*
18 | * Struct to represent a vml object.
19 | */
20 | typedef struct lxw_vml {
21 |
22 | FILE *file;
23 | uint8_t type;
24 | struct lxw_comment_objs *button_objs;
25 | struct lxw_comment_objs *comment_objs;
26 | struct lxw_comment_objs *image_objs;
27 | char *vml_data_id_str;
28 | uint32_t vml_shape_id;
29 | uint8_t comment_display_default;
30 |
31 | } lxw_vml;
32 |
33 |
34 | /* *INDENT-OFF* */
35 | #ifdef __cplusplus
36 | extern "C" {
37 | #endif
38 | /* *INDENT-ON* */
39 |
40 | lxw_vml *lxw_vml_new(void);
41 | void lxw_vml_free(lxw_vml *vml);
42 | void lxw_vml_assemble_xml_file(lxw_vml *self);
43 |
44 | /* Declarations required for unit testing. */
45 | #ifdef TESTING
46 |
47 | #endif /* TESTING */
48 |
49 | /* *INDENT-OFF* */
50 | #ifdef __cplusplus
51 | }
52 | #endif
53 | /* *INDENT-ON* */
54 |
55 | #endif /* __LXW_VML_H__ */
56 |
--------------------------------------------------------------------------------
/libxlsxwriter/include/xlsxwriter/xmlwriter.h:
--------------------------------------------------------------------------------
1 | /*
2 | * libxlsxwriter
3 | *
4 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5 | *
6 | * xmlwriter - A libxlsxwriter library for creating Excel XLSX
7 | * XML files.
8 | *
9 | * The xmlwriter library is used to create the XML sub-components files
10 | * in the Excel XLSX file format.
11 | *
12 | * This library is used in preference to a more generic XML library to allow
13 | * for customization and optimization for the XLSX file format.
14 | *
15 | * The xmlwriter functions are only used internally and do not need to be
16 | * called directly by the end user.
17 | *
18 | */
19 | #ifndef __XMLWRITER_H__
20 | #define __XMLWRITER_H__
21 |
22 | #include
23 | #include
24 | #include
25 | #include "utility.h"
26 |
27 | #define LXW_MAX_ATTRIBUTE_LENGTH 2080 /* Max URL length. */
28 | #define LXW_ATTR_32 32
29 |
30 | #define LXW_ATTRIBUTE_COPY(dst, src) \
31 | do{ \
32 | strncpy(dst, src, LXW_MAX_ATTRIBUTE_LENGTH -1); \
33 | dst[LXW_MAX_ATTRIBUTE_LENGTH - 1] = '\0'; \
34 | } while (0)
35 |
36 |
37 | /* *INDENT-OFF* */
38 | #ifdef __cplusplus
39 | extern "C" {
40 | #endif
41 | /* *INDENT-ON* */
42 |
43 | /* Attribute used in XML elements. */
44 | struct xml_attribute {
45 | char key[LXW_MAX_ATTRIBUTE_LENGTH];
46 | char value[LXW_MAX_ATTRIBUTE_LENGTH];
47 |
48 | /* Make the struct a queue.h list element. */
49 | STAILQ_ENTRY (xml_attribute) list_entries;
50 | };
51 |
52 | /* Use queue.h macros to define the xml_attribute_list type. */
53 | STAILQ_HEAD(xml_attribute_list, xml_attribute);
54 |
55 | /* Create a new attribute struct to add to a xml_attribute_list. */
56 | struct xml_attribute *lxw_new_attribute_str(const char *key,
57 | const char *value);
58 | struct xml_attribute *lxw_new_attribute_int(const char *key, uint64_t value);
59 | struct xml_attribute *lxw_new_attribute_dbl(const char *key, double value);
60 |
61 | /* Macro to initialize the xml_attribute_list pointers. */
62 | #define LXW_INIT_ATTRIBUTES() \
63 | STAILQ_INIT(&attributes)
64 |
65 | /* Macro to add attribute string elements to xml_attribute_list. */
66 | #define LXW_PUSH_ATTRIBUTES_STR(key, value) \
67 | do { \
68 | attribute = lxw_new_attribute_str((key), (value)); \
69 | STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
70 | } while (0)
71 |
72 | /* Macro to add attribute int values to xml_attribute_list. */
73 | #define LXW_PUSH_ATTRIBUTES_INT(key, value) \
74 | do { \
75 | attribute = lxw_new_attribute_int((key), (value)); \
76 | STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
77 | } while (0)
78 |
79 | /* Macro to add attribute double values to xml_attribute_list. */
80 | #define LXW_PUSH_ATTRIBUTES_DBL(key, value) \
81 | do { \
82 | attribute = lxw_new_attribute_dbl((key), (value)); \
83 | STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
84 | } while (0)
85 |
86 | /* Macro to free xml_attribute_list and attribute. */
87 | #define LXW_FREE_ATTRIBUTES() \
88 | do { \
89 | while (!STAILQ_EMPTY(&attributes)) { \
90 | attribute = STAILQ_FIRST(&attributes); \
91 | STAILQ_REMOVE_HEAD(&attributes, list_entries); \
92 | free(attribute); \
93 | } \
94 | } while (0)
95 |
96 | /**
97 | * Create the XML declaration in an XML file.
98 | *
99 | * @param xmlfile A FILE pointer to the output XML file.
100 | */
101 | void lxw_xml_declaration(FILE * xmlfile);
102 |
103 | /**
104 | * Write an XML start tag with optional attributes.
105 | *
106 | * @param xmlfile A FILE pointer to the output XML file.
107 | * @param tag The XML tag to write.
108 | * @param attributes An optional list of attributes to add to the tag.
109 | */
110 | void lxw_xml_start_tag(FILE * xmlfile,
111 | const char *tag,
112 | struct xml_attribute_list *attributes);
113 |
114 | /**
115 | * Write an XML start tag with optional un-encoded attributes.
116 | * This is a minor optimization for attributes that don't need encoding.
117 | *
118 | * @param xmlfile A FILE pointer to the output XML file.
119 | * @param tag The XML tag to write.
120 | * @param attributes An optional list of attributes to add to the tag.
121 | */
122 | void lxw_xml_start_tag_unencoded(FILE * xmlfile,
123 | const char *tag,
124 | struct xml_attribute_list *attributes);
125 |
126 | /**
127 | * Write an XML end tag.
128 | *
129 | * @param xmlfile A FILE pointer to the output XML file.
130 | * @param tag The XML tag to write.
131 | */
132 | void lxw_xml_end_tag(FILE * xmlfile, const char *tag);
133 |
134 | /**
135 | * Write an XML empty tag with optional attributes.
136 | *
137 | * @param xmlfile A FILE pointer to the output XML file.
138 | * @param tag The XML tag to write.
139 | * @param attributes An optional list of attributes to add to the tag.
140 | */
141 | void lxw_xml_empty_tag(FILE * xmlfile,
142 | const char *tag,
143 | struct xml_attribute_list *attributes);
144 |
145 | /**
146 | * Write an XML empty tag with optional un-encoded attributes.
147 | * This is a minor optimization for attributes that don't need encoding.
148 | *
149 | * @param xmlfile A FILE pointer to the output XML file.
150 | * @param tag The XML tag to write.
151 | * @param attributes An optional list of attributes to add to the tag.
152 | */
153 | void lxw_xml_empty_tag_unencoded(FILE * xmlfile,
154 | const char *tag,
155 | struct xml_attribute_list *attributes);
156 |
157 | /**
158 | * Write an XML element containing data and optional attributes.
159 | *
160 | * @param xmlfile A FILE pointer to the output XML file.
161 | * @param tag The XML tag to write.
162 | * @param data The data section of the XML element.
163 | * @param attributes An optional list of attributes to add to the tag.
164 | */
165 | void lxw_xml_data_element(FILE * xmlfile,
166 | const char *tag,
167 | const char *data,
168 | struct xml_attribute_list *attributes);
169 |
170 | void lxw_xml_rich_si_element(FILE * xmlfile, const char *string);
171 |
172 | uint8_t lxw_has_control_characters(const char *string);
173 | char *lxw_escape_control_characters(const char *string);
174 | char *lxw_escape_url_characters(const char *string, uint8_t escape_hash);
175 |
176 | char *lxw_escape_data(const char *data);
177 |
178 | /* *INDENT-OFF* */
179 | #ifdef __cplusplus
180 | }
181 | #endif
182 | /* *INDENT-ON* */
183 |
184 | #endif /* __XMLWRITER_H__ */
185 |
--------------------------------------------------------------------------------
/libxlsxwriter/lib/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Paxa/fast_excel/dc2b5e56e28a26e5f601fde98233a0241a4c4ebd/libxlsxwriter/lib/.gitignore
--------------------------------------------------------------------------------
/libxlsxwriter/libxlsxwriter.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "libxlsxwriter"
3 | s.version = "1.1.5"
4 | s.summary = "Libxlsxwriter: A C library for creating Excel XLSX files."
5 | s.ios.deployment_target = "8.0"
6 | s.osx.deployment_target = "10.8"
7 |
8 | s.description = <<-DESC
9 | Libxlsxwriter is a C library that can be used to write text, numbers, formulas and hyperlinks to multiple worksheets in an Excel 2007+ XLSX file.
10 |
11 | It supports features such as:
12 |
13 | * 100% compatible Excel XLSX files.
14 | * Full Excel formatting.
15 | * Merged cells.
16 | * Defined names.
17 | * Autofilters.
18 | * Charts.
19 | * Data validation and drop down lists.
20 | * Conditional formatting.
21 | * Worksheet PNG/JPEG/GIF images.
22 | * Cell comments.
23 | * Support for adding Macros.
24 | * Memory optimisation mode for writing large files.
25 | * Source code available on [GitHub](https://github.com/jmcnamara/libxlsxwriter).
26 | * FreeBSD license.
27 | * ANSI C.
28 | * Works with GCC, Clang, Xcode, MSVC 2015, ICC, TCC, MinGW, MingGW-w64/32.
29 | * Works on Linux, FreeBSD, OpenBSD, OS X, iOS and Windows. Also works on MSYS/MSYS2 and Cygwin.
30 | * Compiles for 32 and 64 bit.
31 | * Compiles and works on big and little endian systems.
32 | * The only dependency is on `zlib`.
33 | DESC
34 |
35 | s.homepage = "http://libxlsxwriter.github.io"
36 | s.documentation_url = "http://libxlsxwriter.github.io"
37 | s.license = "FreeBSD"
38 | s.author = { "John McNamara" => "jmcnamara@cpan.org" }
39 |
40 | s.source = { :git => "https://github.com/jmcnamara/libxlsxwriter.git", :tag => "RELEASE_" + s.version.to_s }
41 | s.source_files = "src/*.c", "third_party/**/{zip.c,ioapi.c,tmpfileplus.c,md5.c}", "include/**/*.h"
42 | s.preserve_paths = [ 'third_party/**/*.h' ]
43 | s.header_dir = "xlsxwriter"
44 | s.header_mappings_dir = "include"
45 | s.library = "z"
46 | s.compiler_flags = "-DNOCRYPT=1", "-DNOUNCRYPT=1"
47 | s.pod_target_xcconfig = { 'USER_HEADER_SEARCH_PATHS' => '${PODS_ROOT}/libxlsxwriter/include' }
48 | s.module_map = "cocoapods/libxlsxwriter.modulemap"
49 | s.prepare_command = <<-CMD
50 | cp cocoapods/libxlsxwriter-umbrella.h include/xlsxwriter/libxlsxwriter-umbrella.h
51 | CMD
52 | end
53 |
--------------------------------------------------------------------------------
/libxlsxwriter/src/Makefile:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | #
3 | # Makefile for libxlsxwriter library.
4 | #
5 | # Copyright 2014-2022, John McNamara, jmcnamara@cpan.org
6 | #
7 |
8 | # Keep the output quiet by default.
9 | Q=@
10 | ifdef V
11 | Q=
12 | endif
13 |
14 | DESTDIR ?=
15 | PREFIX ?= /usr/local
16 | OPT_LEVEL ?= -O3
17 |
18 | SOVERSION = $(shell sed -n -e 's/.*LXW_SOVERSION \"\(.*\)\"/\1/p' ../include/xlsxwriter.h)
19 |
20 |
21 | # Directory variables.
22 | OBJS_DIR = .
23 | INC_DIR = ../include
24 |
25 | LIBS = -lz
26 |
27 | ifdef USE_SYSTEM_MINIZIP
28 | LIBS += -lminizip
29 | CFLAGS += -DUSE_SYSTEM_MINIZIP
30 | else
31 | # Use the local copy of minizip.
32 | MINIZIP_DIR = ../third_party/minizip
33 | MINIZIP_OBJ = $(MINIZIP_DIR)/ioapi.o $(MINIZIP_DIR)/zip.o
34 | MINIZIP_SO = $(MINIZIP_DIR)/ioapi.so $(MINIZIP_DIR)/zip.so
35 | endif
36 |
37 | ifdef USE_STANDARD_TMPFILE
38 | # Use standard/C tmpfile().
39 | CFLAGS += -DUSE_STANDARD_TMPFILE
40 | else
41 | # Use tmpfileplus (the default).
42 | TMPFILEPLUS_DIR = ../third_party/tmpfileplus
43 | TMPFILEPLUS_OBJ = $(TMPFILEPLUS_DIR)/tmpfileplus.o
44 | TMPFILEPLUS_SO = $(TMPFILEPLUS_DIR)/tmpfileplus.so
45 | endif
46 |
47 | ifdef USE_NO_MD5
48 | # Don't use MD5 to avoid duplicate image files.
49 | CFLAGS += -DUSE_NO_MD5
50 | else
51 | ifdef USE_OPENSSL_MD5
52 | CFLAGS += -DUSE_OPENSSL_MD5 -Wno-deprecated-declarations
53 | LIBS += -lcrypto
54 | else
55 | # Use md5 (the default).
56 | MD5_DIR = ../third_party/md5
57 | MD5_OBJ = $(MD5_DIR)/md5.o
58 | MD5_SO = $(MD5_DIR)/md5.so
59 | endif
60 | endif
61 |
62 | # Set flag for big endian architecture.
63 | ifdef USE_BIG_ENDIAN
64 | CFLAGS += -DLXW_BIG_ENDIAN
65 | endif
66 |
67 | # Use a third party double number formatting function.
68 | ifdef USE_DTOA_LIBRARY
69 | CFLAGS += -DUSE_DTOA_LIBRARY
70 | DTOA_LIB_DIR = ../third_party/dtoa
71 | DTOA_LIB_OBJ = $(DTOA_LIB_DIR)/emyg_dtoa.o
72 | DTOA_LIB_SO = $(DTOA_LIB_DIR)/emyg_dtoa.so
73 | endif
74 |
75 | # Use fmemopen()/open_memstream() to avoid creating temporary files
76 | ifdef USE_MEM_FILE
77 | USE_FMEMOPEN = 1
78 | endif
79 |
80 | ifdef USE_FMEMOPEN
81 | CFLAGS += -DUSE_FMEMOPEN
82 | endif
83 |
84 | # Flags passed to compiler.
85 | CFLAGS += -g $(OPT_LEVEL) -Wall -Wextra -Wstrict-prototypes -pedantic -ansi
86 |
87 | # Ignore icc remarks about inlining limits.
88 | ifeq ($(CC),icc)
89 | CFLAGS +=-diag-disable=11074,11076
90 | endif
91 |
92 | # Library names.
93 | LIBXLSXWRITER_A = libxlsxwriter.a
94 | LIBXLSXWRITER_SO = libxlsxwriter.so.$(SOVERSION)
95 |
96 | # Library with additional non-static functions for testing.
97 | LIBXLSXWRITER_TO = libxlsxwriter_test.a
98 |
99 | # Flags passed to static linker.
100 | ARFLAGS = rc
101 |
102 | # Flags passed to dynamic linker.
103 | FPIC = -fPIC
104 | SOFLAGS = -shared $(FPIC) -Wl,-soname,$(LIBXLSXWRITER_SO)
105 |
106 | # Get Env/OS name.
107 | UNAME := $(shell uname)
108 |
109 | # Change make options on OS X.
110 | ifeq ($(UNAME), Darwin)
111 | LIBXLSXWRITER_SO = libxlsxwriter.$(SOVERSION).dylib
112 | SOFLAGS = -dynamiclib $(FPIC) -compatibility_version $(SOVERSION) -install_name $(PREFIX)/lib/$(LIBXLSXWRITER_SO) $(GCOV)
113 | endif
114 |
115 | # Check for MinGW/MinGW64/Cygwin environments.
116 | ifneq (,$(findstring MINGW, $(UNAME)))
117 | MING_LIKE = y
118 | endif
119 | ifneq (,$(findstring MSYS, $(UNAME)))
120 | MING_LIKE = y
121 | endif
122 | ifneq (,$(findstring CYGWIN, $(UNAME)))
123 | MING_LIKE = y
124 | endif
125 |
126 | # Change make options on MinGW/MinGW64/Cygwin.
127 | ifdef MING_LIKE
128 | LIBXLSXWRITER_SO = libxlsxwriter.dll
129 | FPIC =
130 | CC = gcc
131 | CFLAGS += -Wno-char-subscripts -Wno-long-long
132 | endif
133 |
134 | # Headers as dependecies.
135 | HDRS = $(wildcard ../include/xlsxwriter/*.h)
136 |
137 | # Ojects to compile.
138 | SRCS = $(wildcard *.c)
139 | OBJS = $(patsubst %.c,%.o,$(SRCS))
140 | SOBJS = $(patsubst %.c,%.so,$(SRCS))
141 | TOBJS = $(patsubst %.c,%.to,$(SRCS))
142 | # End of OBJS
143 |
144 | # Build the object files and the libraries.
145 | all : $(LIBXLSXWRITER_A) $(LIBXLSXWRITER_SO)
146 | $(Q)cp $(LIBXLSXWRITER_A) $(LIBXLSXWRITER_SO) ../lib
147 |
148 | ifeq ($(UNAME), Darwin)
149 | $(Q)rm -f ../lib/libxlsxwriter.dylib
150 | $(Q)ln -s $(LIBXLSXWRITER_SO) ../lib/libxlsxwriter.dylib
151 | endif
152 |
153 | ifneq ($(UNAME), Darwin)
154 | $(Q)rm -f ../lib/libxlsxwriter.so
155 | $(Q)ln -s $(LIBXLSXWRITER_SO) ../lib/libxlsxwriter.so
156 | endif
157 |
158 | test_lib : libxlsxwriter_test.a
159 |
160 | # The static library.
161 | $(LIBXLSXWRITER_A) : $(OBJS)
162 | $(Q)$(AR) $(ARFLAGS) $@ $(MINIZIP_OBJ) $(TMPFILEPLUS_OBJ) $(DTOA_LIB_OBJ) $(MD5_OBJ) $^
163 |
164 | # The dynamic library.
165 | ifeq ($(findstring m32,$(CFLAGS)),m32)
166 | ARCH = -m32
167 | endif
168 |
169 | $(LIBXLSXWRITER_SO) : $(SOBJS)
170 | $(Q)$(CC) $(LDFLAGS) $(SOFLAGS) $(ARCH) $(TARGET_ARCH) -o $@ $(MINIZIP_SO) $(TMPFILEPLUS_SO) $(MD5_SO) $(DTOA_LIB_SO) $^ $(LIBS)
171 |
172 | # The test library.
173 | $(LIBXLSXWRITER_TO) : $(TOBJS)
174 | $(Q)$(AR) $(ARFLAGS) $@ $(MINIZIP_OBJ) $(TMPFILEPLUS_OBJ) $(DTOA_LIB_SO) $(MD5_OBJ) $^
175 |
176 | # Minimal target for quick compile without creating the libs.
177 | test_compile : $(OBJS)
178 |
179 | # Targets for the object files.
180 | %.o : %.c $(HDRS)
181 | $(Q)$(CC) -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) $(TARGET_ARCH) $(GCOV) -c $<
182 |
183 | %.so : %.c $(HDRS)
184 | $(Q)$(CC) $(FPIC) -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) $(TARGET_ARCH) $(GCOV) -c $< -o $@
185 |
186 | %.to : %.c $(HDRS)
187 | $(Q)$(CC) -g $(OPT_LEVEL) -DTESTING -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) $(GCOV) -c $< -o $@
188 |
189 |
190 | # Clean up any temp/build files.
191 | clean :
192 | $(Q)rm -f *.o *.a *.so *.so.* *.to *.dylib *.dll *.gcno *.gcda
193 |
--------------------------------------------------------------------------------
/libxlsxwriter/src/custom.c:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * custom - A library for creating Excel custom property files.
3 | *
4 | * Used in conjunction with the libxlsxwriter library.
5 | *
6 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7 | *
8 | */
9 |
10 | #include "xlsxwriter/xmlwriter.h"
11 | #include "xlsxwriter/custom.h"
12 | #include "xlsxwriter/utility.h"
13 |
14 | /*
15 | * Forward declarations.
16 | */
17 |
18 | /*****************************************************************************
19 | *
20 | * Private functions.
21 | *
22 | ****************************************************************************/
23 |
24 | /*
25 | * Create a new custom object.
26 | */
27 | lxw_custom *
28 | lxw_custom_new(void)
29 | {
30 | lxw_custom *custom = calloc(1, sizeof(lxw_custom));
31 | GOTO_LABEL_ON_MEM_ERROR(custom, mem_error);
32 |
33 | return custom;
34 |
35 | mem_error:
36 | lxw_custom_free(custom);
37 | return NULL;
38 | }
39 |
40 | /*
41 | * Free a custom object.
42 | */
43 | void
44 | lxw_custom_free(lxw_custom *custom)
45 | {
46 | if (!custom)
47 | return;
48 |
49 | free(custom);
50 | }
51 |
52 | /*****************************************************************************
53 | *
54 | * XML functions.
55 | *
56 | ****************************************************************************/
57 |
58 | /*
59 | * Write the XML declaration.
60 | */
61 | STATIC void
62 | _custom_xml_declaration(lxw_custom *self)
63 | {
64 | lxw_xml_declaration(self->file);
65 | }
66 |
67 | /*
68 | * Write the element.
69 | */
70 | STATIC void
71 | _chart_write_vt_lpwstr(lxw_custom *self, char *value)
72 | {
73 | lxw_xml_data_element(self->file, "vt:lpwstr", value, NULL);
74 | }
75 |
76 | /*
77 | * Write the element.
78 | */
79 | STATIC void
80 | _chart_write_vt_r_8(lxw_custom *self, double value)
81 | {
82 | char data[LXW_ATTR_32];
83 |
84 | lxw_sprintf_dbl(data, value);
85 |
86 | lxw_xml_data_element(self->file, "vt:r8", data, NULL);
87 | }
88 |
89 | /*
90 | * Write the element.
91 | */
92 | STATIC void
93 | _custom_write_vt_i_4(lxw_custom *self, int32_t value)
94 | {
95 | char data[LXW_ATTR_32];
96 |
97 | lxw_snprintf(data, LXW_ATTR_32, "%d", value);
98 |
99 | lxw_xml_data_element(self->file, "vt:i4", data, NULL);
100 | }
101 |
102 | /*
103 | * Write the element.
104 | */
105 | STATIC void
106 | _custom_write_vt_bool(lxw_custom *self, uint8_t value)
107 | {
108 | if (value)
109 | lxw_xml_data_element(self->file, "vt:bool", "true", NULL);
110 | else
111 | lxw_xml_data_element(self->file, "vt:bool", "false", NULL);
112 | }
113 |
114 | /*
115 | * Write the element.
116 | */
117 | STATIC void
118 | _custom_write_vt_filetime(lxw_custom *self, lxw_datetime *datetime)
119 | {
120 | char data[LXW_DATETIME_LENGTH];
121 |
122 | lxw_snprintf(data, LXW_DATETIME_LENGTH, "%4d-%02d-%02dT%02d:%02d:%02dZ",
123 | datetime->year, datetime->month, datetime->day,
124 | datetime->hour, datetime->min, (int) datetime->sec);
125 |
126 | lxw_xml_data_element(self->file, "vt:filetime", data, NULL);
127 | }
128 |
129 | /*
130 | * Write the element.
131 | */
132 | STATIC void
133 | _chart_write_custom_property(lxw_custom *self,
134 | lxw_custom_property *custom_property)
135 | {
136 | struct xml_attribute_list attributes;
137 | struct xml_attribute *attribute;
138 | char fmtid[] = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}";
139 |
140 | self->pid++;
141 |
142 | LXW_INIT_ATTRIBUTES();
143 | LXW_PUSH_ATTRIBUTES_STR("fmtid", fmtid);
144 | LXW_PUSH_ATTRIBUTES_INT("pid", self->pid + 1);
145 | LXW_PUSH_ATTRIBUTES_STR("name", custom_property->name);
146 |
147 | lxw_xml_start_tag(self->file, "property", &attributes);
148 |
149 | if (custom_property->type == LXW_CUSTOM_STRING) {
150 | /* Write the vt:lpwstr element. */
151 | _chart_write_vt_lpwstr(self, custom_property->u.string);
152 | }
153 | else if (custom_property->type == LXW_CUSTOM_DOUBLE) {
154 | /* Write the vt:r8 element. */
155 | _chart_write_vt_r_8(self, custom_property->u.number);
156 | }
157 | else if (custom_property->type == LXW_CUSTOM_INTEGER) {
158 | /* Write the vt:i4 element. */
159 | _custom_write_vt_i_4(self, custom_property->u.integer);
160 | }
161 | else if (custom_property->type == LXW_CUSTOM_BOOLEAN) {
162 | /* Write the vt:bool element. */
163 | _custom_write_vt_bool(self, custom_property->u.boolean);
164 | }
165 | else if (custom_property->type == LXW_CUSTOM_DATETIME) {
166 | /* Write the vt:filetime element. */
167 | _custom_write_vt_filetime(self, &custom_property->u.datetime);
168 | }
169 |
170 | lxw_xml_end_tag(self->file, "property");
171 |
172 | LXW_FREE_ATTRIBUTES();
173 | }
174 |
175 | /*
176 | * Write the element.
177 | */
178 | STATIC void
179 | _write_custom_properties(lxw_custom *self)
180 | {
181 | struct xml_attribute_list attributes;
182 | struct xml_attribute *attribute;
183 | char xmlns[] = LXW_SCHEMA_OFFICEDOC "/custom-properties";
184 | char xmlns_vt[] = LXW_SCHEMA_OFFICEDOC "/docPropsVTypes";
185 | lxw_custom_property *custom_property;
186 |
187 | LXW_INIT_ATTRIBUTES();
188 | LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
189 | LXW_PUSH_ATTRIBUTES_STR("xmlns:vt", xmlns_vt);
190 |
191 | lxw_xml_start_tag(self->file, "Properties", &attributes);
192 |
193 | STAILQ_FOREACH(custom_property, self->custom_properties, list_pointers) {
194 | _chart_write_custom_property(self, custom_property);
195 | }
196 |
197 | LXW_FREE_ATTRIBUTES();
198 | }
199 |
200 | /*****************************************************************************
201 | *
202 | * XML file assembly functions.
203 | *
204 | ****************************************************************************/
205 |
206 | /*
207 | * Assemble and write the XML file.
208 | */
209 | void
210 | lxw_custom_assemble_xml_file(lxw_custom *self)
211 | {
212 | /* Write the XML declaration. */
213 | _custom_xml_declaration(self);
214 |
215 | _write_custom_properties(self);
216 |
217 | lxw_xml_end_tag(self->file, "Properties");
218 | }
219 |
220 | /*****************************************************************************
221 | *
222 | * Public functions.
223 | *
224 | ****************************************************************************/
225 |
--------------------------------------------------------------------------------
/libxlsxwriter/src/hash_table.c:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * hash_table - Hash table functions for libxlsxwriter.
3 | *
4 | * Used in conjunction with the libxlsxwriter library.
5 | *
6 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7 | *
8 | */
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include "xlsxwriter/hash_table.h"
15 |
16 | /*
17 | * Calculate the hash key using the FNV function. See:
18 | * http://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function
19 | */
20 | STATIC size_t
21 | _generate_hash_key(void *data, size_t data_len, size_t num_buckets)
22 | {
23 | unsigned char *p = data;
24 | size_t hash = 2166136261U;
25 | size_t i;
26 |
27 | for (i = 0; i < data_len; i++)
28 | hash = (hash * 16777619) ^ p[i];
29 |
30 | return hash % num_buckets;
31 | }
32 |
33 | /*
34 | * Check if an element exists in the hash table and return a pointer
35 | * to it if it does.
36 | */
37 | lxw_hash_element *
38 | lxw_hash_key_exists(lxw_hash_table *lxw_hash, void *key, size_t key_len)
39 | {
40 | size_t hash_key = _generate_hash_key(key, key_len, lxw_hash->num_buckets);
41 | struct lxw_hash_bucket_list *list;
42 | lxw_hash_element *element;
43 |
44 | if (!lxw_hash->buckets[hash_key]) {
45 | /* The key isn't in the LXW_HASH hash table. */
46 | return NULL;
47 | }
48 | else {
49 | /* The key is already in the table or there is a hash collision. */
50 | list = lxw_hash->buckets[hash_key];
51 |
52 | /* Iterate over the keys in the bucket's linked list. */
53 | SLIST_FOREACH(element, list, lxw_hash_list_pointers) {
54 | if (memcmp(element->key, key, key_len) == 0) {
55 | /* The key already exists in the table. */
56 | return element;
57 | }
58 | }
59 |
60 | /* Key doesn't exist in the list so this is a hash collision. */
61 | return NULL;
62 | }
63 | }
64 |
65 | /*
66 | * Insert or update a value in the LXW_HASH table based on a key
67 | * and return a pointer to the new or updated element.
68 | */
69 | lxw_hash_element *
70 | lxw_insert_hash_element(lxw_hash_table *lxw_hash, void *key, void *value,
71 | size_t key_len)
72 | {
73 | size_t hash_key = _generate_hash_key(key, key_len, lxw_hash->num_buckets);
74 | struct lxw_hash_bucket_list *list = NULL;
75 | lxw_hash_element *element = NULL;
76 |
77 | if (!lxw_hash->buckets[hash_key]) {
78 | /* The key isn't in the LXW_HASH hash table. */
79 |
80 | /* Create a linked list in the bucket to hold the lxw_hash keys. */
81 | list = calloc(1, sizeof(struct lxw_hash_bucket_list));
82 | GOTO_LABEL_ON_MEM_ERROR(list, mem_error1);
83 |
84 | /* Initialize the bucket linked list. */
85 | SLIST_INIT(list);
86 |
87 | /* Create an lxw_hash element to add to the linked list. */
88 | element = calloc(1, sizeof(lxw_hash_element));
89 | GOTO_LABEL_ON_MEM_ERROR(element, mem_error1);
90 |
91 | /* Store the key and value. */
92 | element->key = key;
93 | element->value = value;
94 |
95 | /* Add the lxw_hash element to the bucket's linked list. */
96 | SLIST_INSERT_HEAD(list, element, lxw_hash_list_pointers);
97 |
98 | /* Also add it to the insertion order linked list. */
99 | STAILQ_INSERT_TAIL(lxw_hash->order_list, element,
100 | lxw_hash_order_pointers);
101 |
102 | /* Store the bucket list at the hash index. */
103 | lxw_hash->buckets[hash_key] = list;
104 |
105 | lxw_hash->used_buckets++;
106 | lxw_hash->unique_count++;
107 |
108 | return element;
109 | }
110 | else {
111 | /* The key is already in the table or there is a hash collision. */
112 | list = lxw_hash->buckets[hash_key];
113 |
114 | /* Iterate over the keys in the bucket's linked list. */
115 | SLIST_FOREACH(element, list, lxw_hash_list_pointers) {
116 | if (memcmp(element->key, key, key_len) == 0) {
117 | /* The key already exists in the table. Update the value. */
118 | if (lxw_hash->free_value)
119 | free(element->value);
120 |
121 | element->value = value;
122 | return element;
123 | }
124 | }
125 |
126 | /* Key doesn't exist in the list so this is a hash collision.
127 | * Create an lxw_hash element to add to the linked list. */
128 | element = calloc(1, sizeof(lxw_hash_element));
129 | GOTO_LABEL_ON_MEM_ERROR(element, mem_error2);
130 |
131 | /* Store the key and value. */
132 | element->key = key;
133 | element->value = value;
134 |
135 | /* Add the lxw_hash element to the bucket linked list. */
136 | SLIST_INSERT_HEAD(list, element, lxw_hash_list_pointers);
137 |
138 | /* Also add it to the insertion order linked list. */
139 | STAILQ_INSERT_TAIL(lxw_hash->order_list, element,
140 | lxw_hash_order_pointers);
141 |
142 | lxw_hash->unique_count++;
143 |
144 | return element;
145 | }
146 |
147 | mem_error1:
148 | free(list);
149 |
150 | mem_error2:
151 | free(element);
152 | return NULL;
153 | }
154 |
155 | /*
156 | * Create a new LXW_HASH hash table object.
157 | */
158 | lxw_hash_table *
159 | lxw_hash_new(uint32_t num_buckets, uint8_t free_key, uint8_t free_value)
160 | {
161 | /* Create the new hash table. */
162 | lxw_hash_table *lxw_hash = calloc(1, sizeof(lxw_hash_table));
163 | RETURN_ON_MEM_ERROR(lxw_hash, NULL);
164 |
165 | lxw_hash->free_key = free_key;
166 | lxw_hash->free_value = free_value;
167 |
168 | /* Add the lxw_hash element buckets. */
169 | lxw_hash->buckets =
170 | calloc(num_buckets, sizeof(struct lxw_hash_bucket_list *));
171 | GOTO_LABEL_ON_MEM_ERROR(lxw_hash->buckets, mem_error);
172 |
173 | /* Add a list for tracking the insertion order. */
174 | lxw_hash->order_list = calloc(1, sizeof(struct lxw_hash_order_list));
175 | GOTO_LABEL_ON_MEM_ERROR(lxw_hash->order_list, mem_error);
176 |
177 | /* Initialize the order list. */
178 | STAILQ_INIT(lxw_hash->order_list);
179 |
180 | /* Store the number of buckets to calculate the load factor. */
181 | lxw_hash->num_buckets = num_buckets;
182 |
183 | return lxw_hash;
184 |
185 | mem_error:
186 | lxw_hash_free(lxw_hash);
187 | return NULL;
188 | }
189 |
190 | /*
191 | * Free the LXW_HASH hash table object.
192 | */
193 | void
194 | lxw_hash_free(lxw_hash_table *lxw_hash)
195 | {
196 | size_t i;
197 | lxw_hash_element *element;
198 | lxw_hash_element *element_temp;
199 |
200 | if (!lxw_hash)
201 | return;
202 |
203 | /* Free the lxw_hash_elements and data using the ordered linked list. */
204 | if (lxw_hash->order_list) {
205 | STAILQ_FOREACH_SAFE(element, lxw_hash->order_list,
206 | lxw_hash_order_pointers, element_temp) {
207 | if (lxw_hash->free_key)
208 | free(element->key);
209 | if (lxw_hash->free_value)
210 | free(element->value);
211 | free(element);
212 | }
213 | }
214 |
215 | /* Free the buckets from the hash table. */
216 | for (i = 0; i < lxw_hash->num_buckets; i++) {
217 | free(lxw_hash->buckets[i]);
218 | }
219 |
220 | free(lxw_hash->order_list);
221 | free(lxw_hash->buckets);
222 | free(lxw_hash);
223 | }
224 |
--------------------------------------------------------------------------------
/libxlsxwriter/src/metadata.c:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * metadata - A library for creating Excel XLSX metadata files.
3 | *
4 | * Used in conjunction with the libxlsxwriter library.
5 | *
6 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7 | *
8 | */
9 |
10 | #include "xlsxwriter/xmlwriter.h"
11 | #include "xlsxwriter/metadata.h"
12 | #include "xlsxwriter/utility.h"
13 |
14 | /*
15 | * Forward declarations.
16 | */
17 |
18 | /*****************************************************************************
19 | *
20 | * Private functions.
21 | *
22 | ****************************************************************************/
23 |
24 | /*
25 | * Create a new metadata object.
26 | */
27 | lxw_metadata *
28 | lxw_metadata_new(void)
29 | {
30 | lxw_metadata *metadata = calloc(1, sizeof(lxw_metadata));
31 | GOTO_LABEL_ON_MEM_ERROR(metadata, mem_error);
32 |
33 | return metadata;
34 |
35 | mem_error:
36 | lxw_metadata_free(metadata);
37 | return NULL;
38 | }
39 |
40 | /*
41 | * Free a metadata object.
42 | */
43 | void
44 | lxw_metadata_free(lxw_metadata *metadata)
45 | {
46 | if (!metadata)
47 | return;
48 |
49 | free(metadata);
50 | }
51 |
52 | /*****************************************************************************
53 | *
54 | * XML functions.
55 | *
56 | ****************************************************************************/
57 |
58 | /*
59 | * Write the XML declaration.
60 | */
61 | STATIC void
62 | _metadata_xml_declaration(lxw_metadata *self)
63 | {
64 | lxw_xml_declaration(self->file);
65 | }
66 |
67 | /*
68 | * Write the element.
69 | */
70 | STATIC void
71 | _metadata_write_metadata(lxw_metadata *self)
72 | {
73 | struct xml_attribute_list attributes;
74 | struct xml_attribute *attribute;
75 | char xmlns[] = "http://schemas.openxmlformats.org/"
76 | "spreadsheetml/2006/main";
77 | char xmlns_xda[] = "http://schemas.microsoft.com/office/"
78 | "spreadsheetml/2017/dynamicarray";
79 |
80 | LXW_INIT_ATTRIBUTES();
81 | LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
82 | LXW_PUSH_ATTRIBUTES_STR("xmlns:xda", xmlns_xda);
83 |
84 | lxw_xml_start_tag(self->file, "metadata", &attributes);
85 |
86 | LXW_FREE_ATTRIBUTES();
87 | }
88 |
89 | /*
90 | * Write the element.
91 | */
92 | STATIC void
93 | _metadata_write_metadata_type(lxw_metadata *self)
94 | {
95 | struct xml_attribute_list attributes;
96 | struct xml_attribute *attribute;
97 |
98 | LXW_INIT_ATTRIBUTES();
99 | LXW_PUSH_ATTRIBUTES_STR("name", "XLDAPR");
100 | LXW_PUSH_ATTRIBUTES_INT("minSupportedVersion", 120000);
101 | LXW_PUSH_ATTRIBUTES_INT("copy", 1);
102 | LXW_PUSH_ATTRIBUTES_INT("pasteAll", 1);
103 | LXW_PUSH_ATTRIBUTES_INT("pasteValues", 1);
104 | LXW_PUSH_ATTRIBUTES_INT("merge", 1);
105 | LXW_PUSH_ATTRIBUTES_INT("splitFirst", 1);
106 | LXW_PUSH_ATTRIBUTES_INT("rowColShift", 1);
107 | LXW_PUSH_ATTRIBUTES_INT("clearFormats", 1);
108 | LXW_PUSH_ATTRIBUTES_INT("clearComments", 1);
109 | LXW_PUSH_ATTRIBUTES_INT("assign", 1);
110 | LXW_PUSH_ATTRIBUTES_INT("coerce", 1);
111 | LXW_PUSH_ATTRIBUTES_INT("cellMeta", 1);
112 |
113 | lxw_xml_empty_tag(self->file, "metadataType", &attributes);
114 |
115 | LXW_FREE_ATTRIBUTES();
116 | }
117 |
118 | /*
119 | * Write the element.
120 | */
121 | STATIC void
122 | _metadata_write_metadata_types(lxw_metadata *self)
123 | {
124 | struct xml_attribute_list attributes;
125 | struct xml_attribute *attribute;
126 |
127 | LXW_INIT_ATTRIBUTES();
128 | LXW_PUSH_ATTRIBUTES_INT("count", 1);
129 |
130 | lxw_xml_start_tag(self->file, "metadataTypes", &attributes);
131 |
132 | /* Write the metadataType element. */
133 | _metadata_write_metadata_type(self);
134 |
135 | lxw_xml_end_tag(self->file, "metadataTypes");
136 |
137 | LXW_FREE_ATTRIBUTES();
138 | }
139 |
140 | /*
141 | * Write the element.
142 | */
143 | STATIC void
144 | _metadata_write_xda_dynamic_array_properties(lxw_metadata *self)
145 | {
146 | struct xml_attribute_list attributes;
147 | struct xml_attribute *attribute;
148 |
149 | LXW_INIT_ATTRIBUTES();
150 | LXW_PUSH_ATTRIBUTES_STR("fDynamic", "1");
151 | LXW_PUSH_ATTRIBUTES_STR("fCollapsed", "0");
152 |
153 | lxw_xml_empty_tag(self->file, "xda:dynamicArrayProperties", &attributes);
154 |
155 | LXW_FREE_ATTRIBUTES();
156 | }
157 |
158 | /*
159 | * Write the element.
160 | */
161 | STATIC void
162 | _metadata_write_ext(lxw_metadata *self)
163 | {
164 | struct xml_attribute_list attributes;
165 | struct xml_attribute *attribute;
166 |
167 | LXW_INIT_ATTRIBUTES();
168 | LXW_PUSH_ATTRIBUTES_STR("uri", "{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}");
169 |
170 | lxw_xml_start_tag(self->file, "ext", &attributes);
171 |
172 | /* Write the xda:dynamicArrayProperties element. */
173 | _metadata_write_xda_dynamic_array_properties(self);
174 |
175 | lxw_xml_end_tag(self->file, "ext");
176 |
177 | LXW_FREE_ATTRIBUTES();
178 | }
179 |
180 | /*
181 | * Write the element.
182 | */
183 | STATIC void
184 | _metadata_write_future_metadata(lxw_metadata *self)
185 | {
186 | struct xml_attribute_list attributes;
187 | struct xml_attribute *attribute;
188 |
189 | LXW_INIT_ATTRIBUTES();
190 | LXW_PUSH_ATTRIBUTES_STR("name", "XLDAPR");
191 | LXW_PUSH_ATTRIBUTES_INT("count", 1);
192 |
193 | lxw_xml_start_tag(self->file, "futureMetadata", &attributes);
194 |
195 | lxw_xml_start_tag(self->file, "bk", NULL);
196 |
197 | lxw_xml_start_tag(self->file, "extLst", NULL);
198 |
199 | /* Write the ext element. */
200 | _metadata_write_ext(self);
201 |
202 | lxw_xml_end_tag(self->file, "extLst");
203 |
204 | lxw_xml_end_tag(self->file, "bk");
205 |
206 | lxw_xml_end_tag(self->file, "futureMetadata");
207 |
208 | LXW_FREE_ATTRIBUTES();
209 | }
210 |
211 | /*
212 | * Write the element.
213 | */
214 | STATIC void
215 | _metadata_write_rc(lxw_metadata *self)
216 | {
217 | struct xml_attribute_list attributes;
218 | struct xml_attribute *attribute;
219 |
220 | LXW_INIT_ATTRIBUTES();
221 | LXW_PUSH_ATTRIBUTES_STR("t", "1");
222 | LXW_PUSH_ATTRIBUTES_STR("v", "0");
223 |
224 | lxw_xml_empty_tag(self->file, "rc", &attributes);
225 |
226 | LXW_FREE_ATTRIBUTES();
227 | }
228 |
229 | /*
230 | * Write the element.
231 | */
232 | STATIC void
233 | _metadata_write_cell_metadata(lxw_metadata *self)
234 | {
235 | struct xml_attribute_list attributes;
236 | struct xml_attribute *attribute;
237 |
238 | LXW_INIT_ATTRIBUTES();
239 | LXW_PUSH_ATTRIBUTES_STR("count", "1");
240 |
241 | lxw_xml_start_tag(self->file, "cellMetadata", &attributes);
242 |
243 | lxw_xml_start_tag(self->file, "bk", NULL);
244 |
245 | /* Write the rc element. */
246 | _metadata_write_rc(self);
247 |
248 | lxw_xml_end_tag(self->file, "bk");
249 |
250 | lxw_xml_end_tag(self->file, "cellMetadata");
251 |
252 | LXW_FREE_ATTRIBUTES();
253 | }
254 |
255 | /*****************************************************************************
256 | *
257 | * XML file assembly functions.
258 | *
259 | ****************************************************************************/
260 |
261 | /*
262 | * Assemble and write the XML file.
263 | */
264 | void
265 | lxw_metadata_assemble_xml_file(lxw_metadata *self)
266 | {
267 | /* Write the XML declaration. */
268 | _metadata_xml_declaration(self);
269 |
270 | /* Write the metadata element. */
271 | _metadata_write_metadata(self);
272 |
273 | /* Write the metadataTypes element. */
274 | _metadata_write_metadata_types(self);
275 |
276 | /* Write the futureMetadata element. */
277 | _metadata_write_future_metadata(self);
278 |
279 | /* Write the cellMetadata element. */
280 | _metadata_write_cell_metadata(self);
281 |
282 | lxw_xml_end_tag(self->file, "metadata");
283 | }
284 |
--------------------------------------------------------------------------------
/libxlsxwriter/src/relationships.c:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * relationships - A library for creating Excel XLSX relationships files.
3 | *
4 | * Used in conjunction with the libxlsxwriter library.
5 | *
6 | * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7 | *
8 | */
9 |
10 | #include
11 | #include "xlsxwriter/xmlwriter.h"
12 | #include "xlsxwriter/relationships.h"
13 | #include "xlsxwriter/utility.h"
14 |
15 | /*
16 | * Forward declarations.
17 | */
18 |
19 | /*****************************************************************************
20 | *
21 | * Private functions.
22 | *
23 | ****************************************************************************/
24 |
25 | /*
26 | * Create a new relationships object.
27 | */
28 | lxw_relationships *
29 | lxw_relationships_new(void)
30 | {
31 | lxw_relationships *rels = calloc(1, sizeof(lxw_relationships));
32 | GOTO_LABEL_ON_MEM_ERROR(rels, mem_error);
33 |
34 | rels->relationships = calloc(1, sizeof(struct lxw_rel_tuples));
35 | GOTO_LABEL_ON_MEM_ERROR(rels->relationships, mem_error);
36 | STAILQ_INIT(rels->relationships);
37 |
38 | return rels;
39 |
40 | mem_error:
41 | lxw_free_relationships(rels);
42 | return NULL;
43 | }
44 |
45 | /*
46 | * Free a relationships object.
47 | */
48 | void
49 | lxw_free_relationships(lxw_relationships *rels)
50 | {
51 | lxw_rel_tuple *relationship;
52 |
53 | if (!rels)
54 | return;
55 |
56 | if (rels->relationships) {
57 | while (!STAILQ_EMPTY(rels->relationships)) {
58 | relationship = STAILQ_FIRST(rels->relationships);
59 | STAILQ_REMOVE_HEAD(rels->relationships, list_pointers);
60 | free(relationship->type);
61 | free(relationship->target);
62 | free(relationship->target_mode);
63 | free(relationship);
64 | }
65 |
66 | free(rels->relationships);
67 | }
68 |
69 | free(rels);
70 | }
71 |
72 | /*****************************************************************************
73 | *
74 | * XML functions.
75 | *
76 | ****************************************************************************/
77 |
78 | /*
79 | * Write the XML declaration.
80 | */
81 | STATIC void
82 | _relationships_xml_declaration(lxw_relationships *self)
83 | {
84 | lxw_xml_declaration(self->file);
85 | }
86 |
87 | /*
88 | * Write the element.
89 | */
90 | STATIC void
91 | _write_relationship(lxw_relationships *self, const char *type,
92 | const char *target, const char *target_mode)
93 | {
94 | struct xml_attribute_list attributes;
95 | struct xml_attribute *attribute;
96 | char r_id[LXW_MAX_ATTRIBUTE_LENGTH] = { 0 };
97 |
98 | self->rel_id++;
99 | lxw_snprintf(r_id, LXW_ATTR_32, "rId%d", self->rel_id);
100 |
101 | LXW_INIT_ATTRIBUTES();
102 | LXW_PUSH_ATTRIBUTES_STR("Id", r_id);
103 | LXW_PUSH_ATTRIBUTES_STR("Type", type);
104 | LXW_PUSH_ATTRIBUTES_STR("Target", target);
105 |
106 | if (target_mode)
107 | LXW_PUSH_ATTRIBUTES_STR("TargetMode", target_mode);
108 |
109 | lxw_xml_empty_tag(self->file, "Relationship", &attributes);
110 |
111 | LXW_FREE_ATTRIBUTES();
112 | }
113 |
114 | /*
115 | * Write the element.
116 | */
117 | STATIC void
118 | _write_relationships(lxw_relationships *self)
119 | {
120 | struct xml_attribute_list attributes;
121 | struct xml_attribute *attribute;
122 | lxw_rel_tuple *rel;
123 |
124 | LXW_INIT_ATTRIBUTES();
125 | LXW_PUSH_ATTRIBUTES_STR("xmlns", LXW_SCHEMA_PACKAGE);
126 |
127 | lxw_xml_start_tag(self->file, "Relationships", &attributes);
128 |
129 | STAILQ_FOREACH(rel, self->relationships, list_pointers) {
130 | _write_relationship(self, rel->type, rel->target, rel->target_mode);
131 | }
132 |
133 | LXW_FREE_ATTRIBUTES();
134 | }
135 |
136 | /*****************************************************************************
137 | *
138 | * XML file assembly functions.
139 | *
140 | ****************************************************************************/
141 |
142 | /*
143 | * Assemble and write the XML file.
144 | */
145 | void
146 | lxw_relationships_assemble_xml_file(lxw_relationships *self)
147 | {
148 | /* Write the XML declaration. */
149 | _relationships_xml_declaration(self);
150 |
151 | _write_relationships(self);
152 |
153 | /* Close the relationships tag. */
154 | lxw_xml_end_tag(self->file, "Relationships");
155 | }
156 |
157 | /*
158 | * Add a generic container relationship to XLSX .rels xml files.
159 | */
160 | STATIC void
161 | _add_relationship(lxw_relationships *self, const char *schema,
162 | const char *type, const char *target,
163 | const char *target_mode)
164 | {
165 | lxw_rel_tuple *relationship;
166 |
167 | if (!schema || !type || !target)
168 | return;
169 |
170 | relationship = calloc(1, sizeof(lxw_rel_tuple));
171 | GOTO_LABEL_ON_MEM_ERROR(relationship, mem_error);
172 |
173 | relationship->type = calloc(1, LXW_MAX_ATTRIBUTE_LENGTH);
174 | GOTO_LABEL_ON_MEM_ERROR(relationship->type, mem_error);
175 |
176 | /* Add the schema to the relationship type. */
177 | lxw_snprintf(relationship->type, LXW_MAX_ATTRIBUTE_LENGTH, "%s%s",
178 | schema, type);
179 |
180 | relationship->target = lxw_strdup(target);
181 | GOTO_LABEL_ON_MEM_ERROR(relationship->target, mem_error);
182 |
183 | if (target_mode) {
184 | relationship->target_mode = lxw_strdup(target_mode);
185 | GOTO_LABEL_ON_MEM_ERROR(relationship->target_mode, mem_error);
186 | }
187 |
188 | STAILQ_INSERT_TAIL(self->relationships, relationship, list_pointers);
189 |
190 | return;
191 |
192 | mem_error:
193 | if (relationship) {
194 | free(relationship->type);
195 | free(relationship->target);
196 | free(relationship->target_mode);
197 | free(relationship);
198 | }
199 | }
200 |
201 | /*****************************************************************************
202 | *
203 | * Public functions.
204 | *
205 | ****************************************************************************/
206 |
207 | /*
208 | * Add a document relationship to XLSX .rels xml files.
209 | */
210 | void
211 | lxw_add_document_relationship(lxw_relationships *self, const char *type,
212 | const char *target)
213 | {
214 | _add_relationship(self, LXW_SCHEMA_DOCUMENT, type, target, NULL);
215 | }
216 |
217 | /*
218 | * Add a package relationship to XLSX .rels xml files.
219 | */
220 | void
221 | lxw_add_package_relationship(lxw_relationships *self, const char *type,
222 | const char *target)
223 | {
224 | _add_relationship(self, LXW_SCHEMA_PACKAGE, type, target, NULL);
225 | }
226 |
227 | /*
228 | * Add a MS schema package relationship to XLSX .rels xml files.
229 | */
230 | void
231 | lxw_add_ms_package_relationship(lxw_relationships *self, const char *type,
232 | const char *target)
233 | {
234 | _add_relationship(self, LXW_SCHEMA_MS, type, target, NULL);
235 | }
236 |
237 | /*
238 | * Add a worksheet relationship to sheet .rels xml files.
239 | */
240 | void
241 | lxw_add_worksheet_relationship(lxw_relationships *self, const char *type,
242 | const char *target, const char *target_mode)
243 | {
244 | _add_relationship(self, LXW_SCHEMA_DOCUMENT, type, target, target_mode);
245 | }
246 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/dtoa/Makefile:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | #
3 | # Simplied Makefile to build the emyg_dtoa library for libxlsxwriter.
4 | #
5 |
6 | # Keep the output quiet by default.
7 | Q=@
8 | ifdef V
9 | Q=
10 | endif
11 |
12 | UNAME := $(shell uname)
13 |
14 | # Check for MinGW/MinGW64/Cygwin environments.
15 | ifneq (,$(findstring MINGW, $(UNAME)))
16 | MING_LIKE = y
17 | endif
18 | ifneq (,$(findstring MSYS, $(UNAME)))
19 | MING_LIKE = y
20 | endif
21 | ifneq (,$(findstring CYGWIN, $(UNAME)))
22 | MING_LIKE = y
23 | endif
24 |
25 | FPIC = -fPIC
26 |
27 | # Change make options on MinGW/MinGW64/Cygwin.
28 | ifdef MING_LIKE
29 | FPIC =
30 | CC = gcc
31 | endif
32 |
33 | all: emyg_dtoa.o emyg_dtoa.so
34 |
35 | %.o : %.c
36 | $(Q)$(CC) -c $(CFLAGS) $<
37 |
38 | %.so : %.c
39 | $(Q)$(CC) $(FPIC) -c $(CFLAGS) $< -o $@
40 |
41 | clean:
42 | $(Q)rm -f *.o *.so
43 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/dtoa/emyg_dtoa.h:
--------------------------------------------------------------------------------
1 | /* emyg_dtoa.h
2 | ** Copyright (C) 2015 Doug Currie
3 | ** based on dtoa_milo.h
4 | ** Copyright (C) 2014 Milo Yip
5 | **
6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy
7 | ** of this software and associated documentation files (the "Software"), to deal
8 | ** in the Software without restriction, including without limitation the rights
9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | ** copies of the Software, and to permit persons to whom the Software is
11 | ** furnished to do so, subject to the following conditions:
12 | **
13 | ** The above copyright notice and this permission notice shall be included in
14 | ** all copies or substantial portions of the Software.
15 | **
16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | ** THE SOFTWARE.
23 | */
24 |
25 | /* Source from https://github.com/miloyip/dtoa-benchmark */
26 | void emyg_dtoa (double value, char* buffer);
27 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/md5/Makefile:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | #
3 | # Simplied Makefile to build the openwall md5 library for libxlsxwriter.
4 | #
5 |
6 | # Keep the output quiet by default.
7 | Q=@
8 | ifdef V
9 | Q=
10 | endif
11 |
12 | UNAME := $(shell uname)
13 |
14 | # Check for MinGW/MinGW64/Cygwin environments.
15 | ifneq (,$(findstring MINGW, $(UNAME)))
16 | MING_LIKE = y
17 | endif
18 | ifneq (,$(findstring MSYS, $(UNAME)))
19 | MING_LIKE = y
20 | endif
21 | ifneq (,$(findstring CYGWIN, $(UNAME)))
22 | MING_LIKE = y
23 | endif
24 |
25 | FPIC = -fPIC
26 |
27 | # Change make options on MinGW/MinGW64/Cygwin.
28 | ifdef MING_LIKE
29 | FPIC =
30 | CC = gcc
31 | endif
32 |
33 | all: md5.o md5.so
34 |
35 | %.o : %.c
36 | $(Q)$(CC) -c $(CFLAGS) $(TARGET_ARCH) $<
37 |
38 | %.so : %.c
39 | $(Q)$(CC) $(FPIC) -c $(CFLAGS) $(TARGET_ARCH) $< -o $@
40 |
41 | clean:
42 | $(Q)rm -f *.o *.so
43 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/md5/md5.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
3 | * MD5 Message-Digest Algorithm (RFC 1321).
4 | *
5 | * Homepage:
6 | * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
7 | *
8 | * Author:
9 | * Alexander Peslyak, better known as Solar Designer
10 | *
11 | * This software was written by Alexander Peslyak in 2001. No copyright is
12 | * claimed, and the software is hereby placed in the public domain.
13 | * In case this attempt to disclaim copyright and place the software in the
14 | * public domain is deemed null and void, then the software is
15 | * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
16 | * general public under the following terms:
17 | *
18 | * Redistribution and use in source and binary forms, with or without
19 | * modification, are permitted.
20 | *
21 | * There's ABSOLUTELY NO WARRANTY, express or implied.
22 | *
23 | * See md5.c for more information.
24 | */
25 |
26 | #ifdef HAVE_OPENSSL
27 | #include
28 | #elif !defined(_MD5_H)
29 | #define _MD5_H
30 |
31 | /* Any 32-bit or wider unsigned integer data type will do */
32 | typedef unsigned int MD5_u32plus;
33 |
34 | typedef struct {
35 | MD5_u32plus lo, hi;
36 | MD5_u32plus a, b, c, d;
37 | unsigned char buffer[64];
38 | MD5_u32plus block[16];
39 | } MD5_CTX;
40 |
41 | extern void MD5_Init(MD5_CTX *ctx);
42 | extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
43 | extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/Makefile:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | #
3 | # Simplied Makefile to build the minizip objects for the libxlsxwriter library.
4 | #
5 |
6 | # Keep the output quiet by default.
7 | Q=@
8 | ifdef V
9 | Q=
10 | endif
11 |
12 | UNAME := $(shell uname -sr)
13 |
14 | # Check for MinGW/MinGW64/Cygwin environments.
15 | ifneq (,$(findstring MINGW, $(UNAME)))
16 | MING_LIKE = y
17 | endif
18 | ifneq (,$(findstring MSYS, $(UNAME)))
19 | MING_LIKE = y
20 | endif
21 | ifneq (,$(findstring CYGWIN, $(UNAME)))
22 | MING_LIKE = y
23 | endif
24 |
25 | FPIC = -fPIC
26 | CFLAGS += -O3 -DNOCRYPT -DNOUNCRYPT
27 |
28 | # Change make options on MinGW/MinGW64/Cygwin.
29 | ifdef MING_LIKE
30 | FPIC =
31 | CC = gcc
32 | CFLAGS += -DUSE_FILE32API
33 | endif
34 |
35 | all: ioapi.o zip.o ioapi.so zip.so
36 |
37 | %.o : %.c
38 | $(Q)$(CC) -c $(CFLAGS) $(TARGET_ARCH) $<
39 |
40 | %.so : %.c
41 | $(Q)$(CC) $(FPIC) -c $(CFLAGS) $(TARGET_ARCH) $< -o $@
42 |
43 | clean:
44 | $(Q)rm -f *.o *.so
45 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/Makefile.am:
--------------------------------------------------------------------------------
1 | lib_LTLIBRARIES = libminizip.la
2 |
3 | if COND_DEMOS
4 | bin_PROGRAMS = miniunzip minizip
5 | endif
6 |
7 | zlib_top_srcdir = $(top_srcdir)/../..
8 | zlib_top_builddir = $(top_builddir)/../..
9 |
10 | AM_CPPFLAGS = -I$(zlib_top_srcdir)
11 | AM_LDFLAGS = -L$(zlib_top_builddir)
12 |
13 | if WIN32
14 | iowin32_src = iowin32.c
15 | iowin32_h = iowin32.h
16 | endif
17 |
18 | libminizip_la_SOURCES = \
19 | ioapi.c \
20 | mztools.c \
21 | unzip.c \
22 | zip.c \
23 | ${iowin32_src}
24 |
25 | libminizip_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0 -lz
26 |
27 | minizip_includedir = $(includedir)/minizip
28 | minizip_include_HEADERS = \
29 | crypt.h \
30 | ioapi.h \
31 | mztools.h \
32 | unzip.h \
33 | zip.h \
34 | ${iowin32_h}
35 |
36 | pkgconfigdir = $(libdir)/pkgconfig
37 | pkgconfig_DATA = minizip.pc
38 |
39 | EXTRA_PROGRAMS = miniunzip minizip
40 |
41 | miniunzip_SOURCES = miniunz.c
42 | miniunzip_LDADD = libminizip.la
43 |
44 | minizip_SOURCES = minizip.c
45 | minizip_LDADD = libminizip.la -lz
46 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/Makefile.orig:
--------------------------------------------------------------------------------
1 | CC=cc
2 | CFLAGS := $(CFLAGS) -O -I../..
3 |
4 | UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
5 | ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a
6 |
7 | .c.o:
8 | $(CC) -c $(CFLAGS) $*.c
9 |
10 | all: miniunz minizip
11 |
12 | miniunz: $(UNZ_OBJS)
13 | $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)
14 |
15 | minizip: $(ZIP_OBJS)
16 | $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS)
17 |
18 | test: miniunz minizip
19 | @rm -f test.*
20 | @echo hello hello hello > test.txt
21 | ./minizip test test.txt
22 | ./miniunz -l test.zip
23 | @mv test.txt test.old
24 | ./miniunz test.zip
25 | @cmp test.txt test.old
26 | @rm -f test.*
27 |
28 | clean:
29 | /bin/rm -f *.o *~ minizip miniunz test.*
30 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt:
--------------------------------------------------------------------------------
1 |
2 | MiniZip 1.1 was derived from MiniZip at version 1.01f
3 |
4 | Change in 1.0 (Okt 2009)
5 | - **TODO - Add history**
6 |
7 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/MiniZip64_info.txt:
--------------------------------------------------------------------------------
1 | MiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson
2 |
3 | Introduction
4 | ---------------------
5 | MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant ( http://www.winimage.com/zLibDll/minizip.html )
6 |
7 | When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0.
8 | All possible work was done for compatibility.
9 |
10 |
11 | Background
12 | ---------------------
13 | When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64
14 | support for unzip.c into minizip for a open source project called gdal ( http://www.gdal.org/ )
15 |
16 | That was used as a starting point. And after that ZIP64 support was added to zip.c
17 | some refactoring and code cleanup was also done.
18 |
19 |
20 | Changed from MiniZip 1.0 to MiniZip 1.1
21 | ---------------------------------------
22 | * Added ZIP64 support for unzip ( by Even Rouault )
23 | * Added ZIP64 support for zip ( by Mathias Svensson )
24 | * Reverted some changed that Even Rouault did.
25 | * Bunch of patches received from Gulles Vollant that he received for MiniZip from various users.
26 | * Added unzip patch for BZIP Compression method (patch create by Daniel Borca)
27 | * Added BZIP Compress method for zip
28 | * Did some refactoring and code cleanup
29 |
30 |
31 | Credits
32 |
33 | Gilles Vollant - Original MiniZip author
34 | Even Rouault - ZIP64 unzip Support
35 | Daniel Borca - BZip Compression method support in unzip
36 | Mathias Svensson - ZIP64 zip support
37 | Mathias Svensson - BZip Compression method support in zip
38 |
39 | Resources
40 |
41 | ZipLayout http://result42.com/projects/ZipFileLayout
42 | Command line tool for Windows that shows the layout and information of the headers in a zip archive.
43 | Used when debugging and validating the creation of zip files using MiniZip64
44 |
45 |
46 | ZIP App Note http://www.pkware.com/documents/casestudies/APPNOTE.TXT
47 | Zip File specification
48 |
49 |
50 | Notes.
51 | * To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined.
52 |
53 | License
54 | ----------------------------------------------------------
55 | Condition of use and distribution are the same than zlib :
56 |
57 | This software is provided 'as-is', without any express or implied
58 | warranty. In no event will the authors be held liable for any damages
59 | arising from the use of this software.
60 |
61 | Permission is granted to anyone to use this software for any purpose,
62 | including commercial applications, and to alter it and redistribute it
63 | freely, subject to the following restrictions:
64 |
65 | 1. The origin of this software must not be misrepresented; you must not
66 | claim that you wrote the original software. If you use this software
67 | in a product, an acknowledgment in the product documentation would be
68 | appreciated but is not required.
69 | 2. Altered source versions must be plainly marked as such, and must not be
70 | misrepresented as being the original software.
71 | 3. This notice may not be removed or altered from any source distribution.
72 |
73 | ----------------------------------------------------------
74 |
75 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/README.txt:
--------------------------------------------------------------------------------
1 | The souce files in this directory are included in libxlsxwriter from the
2 | contrib/minizip/ directory of zlib-1.2.8.
3 |
4 | The files zip.h and ioapi.h have had a small number of comments modifed from
5 | C++ to C style to avoid warnings with -pedantic -ansi.
6 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/configure.ac:
--------------------------------------------------------------------------------
1 | # -*- Autoconf -*-
2 | # Process this file with autoconf to produce a configure script.
3 |
4 | AC_INIT([minizip], [1.3.0], [bugzilla.redhat.com])
5 | AC_CONFIG_SRCDIR([minizip.c])
6 | AM_INIT_AUTOMAKE([foreign])
7 | LT_INIT
8 |
9 | AC_MSG_CHECKING([whether to build example programs])
10 | AC_ARG_ENABLE([demos], AC_HELP_STRING([--enable-demos], [build example programs]))
11 | AM_CONDITIONAL([COND_DEMOS], [test "$enable_demos" = yes])
12 | if test "$enable_demos" = yes
13 | then
14 | AC_MSG_RESULT([yes])
15 | else
16 | AC_MSG_RESULT([no])
17 | fi
18 |
19 | case "${host}" in
20 | *-mingw* | mingw*)
21 | WIN32="yes"
22 | ;;
23 | *)
24 | ;;
25 | esac
26 | AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"])
27 |
28 |
29 | AC_SUBST([HAVE_UNISTD_H], [0])
30 | AC_CHECK_HEADER([unistd.h], [HAVE_UNISTD_H=1], [])
31 | AC_CONFIG_FILES([Makefile minizip.pc])
32 | AC_OUTPUT
33 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/crypt.h:
--------------------------------------------------------------------------------
1 | /* crypt.h -- base code for crypt/uncrypt ZIPfile
2 |
3 |
4 | Version 1.01e, February 12th, 2005
5 |
6 | Copyright (C) 1998-2005 Gilles Vollant
7 |
8 | This code is a modified version of crypting code in Infozip distribution
9 |
10 | The encryption/decryption parts of this source code (as opposed to the
11 | non-echoing password parts) were originally written in Europe. The
12 | whole source package can be freely distributed, including from the USA.
13 | (Prior to January 2000, re-export from the US was a violation of US law.)
14 |
15 | This encryption code is a direct transcription of the algorithm from
16 | Roger Schlafly, described by Phil Katz in the file appnote.txt. This
17 | file (appnote.txt) is distributed with the PKZIP program (even in the
18 | version without encryption capabilities).
19 |
20 | If you don't need crypting in your application, just define symbols
21 | NOCRYPT and NOUNCRYPT.
22 |
23 | This code support the "Traditional PKWARE Encryption".
24 |
25 | The new AES encryption added on Zip format by Winzip (see the page
26 | http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
27 | Encryption is not supported.
28 | */
29 |
30 | #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
31 |
32 | /***********************************************************************
33 | * Return the next byte in the pseudo-random sequence
34 | */
35 | static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) {
36 | unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
37 | * unpredictable manner on 16-bit systems; not a problem
38 | * with any known compiler so far, though */
39 |
40 | (void)pcrc_32_tab;
41 | temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
42 | return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
43 | }
44 |
45 | /***********************************************************************
46 | * Update the encryption keys with the next byte of plain text
47 | */
48 | static int update_keys(unsigned long* pkeys, const z_crc_t* pcrc_32_tab, int c) {
49 | (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
50 | (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
51 | (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
52 | {
53 | register int keyshift = (int)((*(pkeys+1)) >> 24);
54 | (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
55 | }
56 | return c;
57 | }
58 |
59 |
60 | /***********************************************************************
61 | * Initialize the encryption keys and the random header according to
62 | * the given password.
63 | */
64 | static void init_keys(const char* passwd, unsigned long* pkeys, const z_crc_t* pcrc_32_tab) {
65 | *(pkeys+0) = 305419896L;
66 | *(pkeys+1) = 591751049L;
67 | *(pkeys+2) = 878082192L;
68 | while (*passwd != '\0') {
69 | update_keys(pkeys,pcrc_32_tab,(int)*passwd);
70 | passwd++;
71 | }
72 | }
73 |
74 | #define zdecode(pkeys,pcrc_32_tab,c) \
75 | (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
76 |
77 | #define zencode(pkeys,pcrc_32_tab,c,t) \
78 | (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), (Byte)t^(c))
79 |
80 | #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
81 |
82 | #define RAND_HEAD_LEN 12
83 | /* "last resort" source for second part of crypt seed pattern */
84 | # ifndef ZCR_SEED2
85 | # define ZCR_SEED2 3141592654UL /* use PI as default pattern */
86 | # endif
87 |
88 | static unsigned crypthead(const char* passwd, /* password string */
89 | unsigned char* buf, /* where to write header */
90 | int bufSize,
91 | unsigned long* pkeys,
92 | const z_crc_t* pcrc_32_tab,
93 | unsigned long crcForCrypting) {
94 | unsigned n; /* index in random header */
95 | int t; /* temporary */
96 | int c; /* random byte */
97 | unsigned char header[RAND_HEAD_LEN-2]; /* random header */
98 | static unsigned calls = 0; /* ensure different random header each time */
99 |
100 | if (bufSize> 7) & 0xff;
115 | header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
116 | }
117 | /* Encrypt random header (last two bytes is high word of crc) */
118 | init_keys(passwd, pkeys, pcrc_32_tab);
119 | for (n = 0; n < RAND_HEAD_LEN-2; n++)
120 | {
121 | buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
122 | }
123 | buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
124 | buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
125 | return n;
126 | }
127 |
128 | #endif
129 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/ioapi.h:
--------------------------------------------------------------------------------
1 | /* ioapi.h -- IO base function header for compress/uncompress .zip
2 | part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
3 |
4 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
5 |
6 | Modifications for Zip64 support
7 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
8 |
9 | For more info read MiniZip_info.txt
10 |
11 | Changes
12 |
13 | Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
14 | Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
15 | More if/def section may be needed to support other platforms
16 | Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
17 | (but you should use iowin32.c for windows instead)
18 |
19 | */
20 |
21 |
22 | /* Pragma added by libxlsxwriter to avoid warnings with -pedantic -ansi. */
23 | #ifndef _WIN32
24 | #pragma GCC system_header
25 | #endif
26 |
27 | #ifndef _ZLIBIOAPI64_H
28 | #define _ZLIBIOAPI64_H
29 |
30 | #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
31 |
32 | // Linux needs this to support file operation on files larger then 4+GB
33 | // But might need better if/def to select just the platforms that needs them.
34 |
35 | #ifndef __USE_FILE_OFFSET64
36 | #define __USE_FILE_OFFSET64
37 | #endif
38 | #ifndef __USE_LARGEFILE64
39 | #define __USE_LARGEFILE64
40 | #endif
41 | #ifndef _LARGEFILE64_SOURCE
42 | #define _LARGEFILE64_SOURCE
43 | #endif
44 | #ifndef _FILE_OFFSET_BIT
45 | #define _FILE_OFFSET_BIT 64
46 | #endif
47 |
48 | #endif
49 |
50 | #include
51 | #include
52 | #include "zlib.h"
53 |
54 | #if defined(USE_FILE32API)
55 | #define fopen64 fopen
56 | #define ftello64 ftell
57 | #define fseeko64 fseek
58 | #else
59 | #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
60 | #define fopen64 fopen
61 | #define ftello64 ftello
62 | #define fseeko64 fseeko
63 | #endif
64 | #ifdef _MSC_VER
65 | #define fopen64 fopen
66 | #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
67 | #define ftello64 _ftelli64
68 | #define fseeko64 _fseeki64
69 | #else // old MSC
70 | #define ftello64 ftell
71 | #define fseeko64 fseek
72 | #endif
73 | #endif
74 | #endif
75 |
76 | /*
77 | #ifndef ZPOS64_T
78 | #ifdef _WIN32
79 | #define ZPOS64_T fpos_t
80 | #else
81 | #include
82 | #define ZPOS64_T uint64_t
83 | #endif
84 | #endif
85 | */
86 |
87 | #ifdef HAVE_MINIZIP64_CONF_H
88 | #include "mz64conf.h"
89 | #endif
90 |
91 | /* a type chosen by DEFINE */
92 | #ifdef HAVE_64BIT_INT_CUSTOM
93 | typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
94 | #else
95 | #ifdef HAS_STDINT_H
96 | #include "stdint.h"
97 | typedef uint64_t ZPOS64_T;
98 | #else
99 |
100 |
101 |
102 | #if defined(_MSC_VER) || defined(__BORLANDC__)
103 | typedef unsigned __int64 ZPOS64_T;
104 | #else
105 | typedef unsigned long long int ZPOS64_T;
106 | #endif
107 | #endif
108 | #endif
109 |
110 | /* Maximum unsigned 32-bit value used as placeholder for zip64 */
111 | #ifndef MAXU32
112 | #define MAXU32 (0xffffffff)
113 | #endif
114 |
115 | #ifdef __cplusplus
116 | extern "C" {
117 | #endif
118 |
119 |
120 | #define ZLIB_FILEFUNC_SEEK_CUR (1)
121 | #define ZLIB_FILEFUNC_SEEK_END (2)
122 | #define ZLIB_FILEFUNC_SEEK_SET (0)
123 |
124 | #define ZLIB_FILEFUNC_MODE_READ (1)
125 | #define ZLIB_FILEFUNC_MODE_WRITE (2)
126 | #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
127 |
128 | #define ZLIB_FILEFUNC_MODE_EXISTING (4)
129 | #define ZLIB_FILEFUNC_MODE_CREATE (8)
130 |
131 |
132 | #ifndef ZCALLBACK
133 | #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
134 | #define ZCALLBACK CALLBACK
135 | #else
136 | #define ZCALLBACK
137 | #endif
138 | #endif
139 |
140 |
141 |
142 |
143 | typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode);
144 | typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size);
145 | typedef uLong (ZCALLBACK *write_file_func) (voidpf opaque, voidpf stream, const void* buf, uLong size);
146 | typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream);
147 | typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream);
148 |
149 | typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream);
150 | typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
151 |
152 |
153 | /* here is the "old" 32 bits structure structure */
154 | typedef struct zlib_filefunc_def_s
155 | {
156 | open_file_func zopen_file;
157 | read_file_func zread_file;
158 | write_file_func zwrite_file;
159 | tell_file_func ztell_file;
160 | seek_file_func zseek_file;
161 | close_file_func zclose_file;
162 | testerror_file_func zerror_file;
163 | voidpf opaque;
164 | } zlib_filefunc_def;
165 |
166 | typedef ZPOS64_T (ZCALLBACK *tell64_file_func) (voidpf opaque, voidpf stream);
167 | typedef long (ZCALLBACK *seek64_file_func) (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin);
168 | typedef voidpf (ZCALLBACK *open64_file_func) (voidpf opaque, const void* filename, int mode);
169 |
170 | typedef struct zlib_filefunc64_def_s
171 | {
172 | open64_file_func zopen64_file;
173 | read_file_func zread_file;
174 | write_file_func zwrite_file;
175 | tell64_file_func ztell64_file;
176 | seek64_file_func zseek64_file;
177 | close_file_func zclose_file;
178 | testerror_file_func zerror_file;
179 | voidpf opaque;
180 | } zlib_filefunc64_def;
181 |
182 | void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def);
183 | void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def);
184 |
185 | /* now internal definition, only for zip.c and unzip.h */
186 | typedef struct zlib_filefunc64_32_def_s
187 | {
188 | zlib_filefunc64_def zfile_func64;
189 | open_file_func zopen32_file;
190 | tell_file_func ztell32_file;
191 | seek_file_func zseek32_file;
192 | } zlib_filefunc64_32_def;
193 |
194 |
195 | #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
196 | #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
197 | //#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
198 | //#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
199 | #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
200 | #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
201 |
202 | voidpf call_zopen64(const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode);
203 | long call_zseek64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin);
204 | ZPOS64_T call_ztell64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream);
205 |
206 | void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
207 |
208 | #define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
209 | #define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
210 | #define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
211 |
212 | #ifdef __cplusplus
213 | }
214 | #endif
215 |
216 | #endif
217 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/iowin32.h:
--------------------------------------------------------------------------------
1 | /* iowin32.h -- IO base function header for compress/uncompress .zip
2 | Version 1.1, February 14h, 2010
3 | part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
4 |
5 | Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
6 |
7 | Modifications for Zip64 support
8 | Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
9 |
10 | For more info read MiniZip_info.txt
11 |
12 | */
13 |
14 | #include
15 |
16 |
17 | #ifdef __cplusplus
18 | extern "C" {
19 | #endif
20 |
21 | void fill_win32_filefunc(zlib_filefunc_def* pzlib_filefunc_def);
22 | void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def);
23 | void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def);
24 | void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def);
25 |
26 | #ifdef __cplusplus
27 | }
28 | #endif
29 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/make_vms.com:
--------------------------------------------------------------------------------
1 | $ if f$search("ioapi.h_orig") .eqs. "" then copy ioapi.h ioapi.h_orig
2 | $ open/write zdef vmsdefs.h
3 | $ copy sys$input: zdef
4 | $ deck
5 | #define unix
6 | #define fill_zlib_filefunc64_32_def_from_filefunc32 fillzffunc64from
7 | #define Write_Zip64EndOfCentralDirectoryLocator Write_Zip64EoDLocator
8 | #define Write_Zip64EndOfCentralDirectoryRecord Write_Zip64EoDRecord
9 | #define Write_EndOfCentralDirectoryRecord Write_EoDRecord
10 | $ eod
11 | $ close zdef
12 | $ copy vmsdefs.h,ioapi.h_orig ioapi.h
13 | $ cc/include=[--]/prefix=all ioapi.c
14 | $ cc/include=[--]/prefix=all miniunz.c
15 | $ cc/include=[--]/prefix=all unzip.c
16 | $ cc/include=[--]/prefix=all minizip.c
17 | $ cc/include=[--]/prefix=all zip.c
18 | $ link miniunz,unzip,ioapi,[--]libz.olb/lib
19 | $ link minizip,zip,ioapi,[--]libz.olb/lib
20 | $ mcr []minizip test minizip_info.txt
21 | $ mcr []miniunz -l test.zip
22 | $ rename minizip_info.txt; minizip_info.txt_old
23 | $ mcr []miniunz test.zip
24 | $ delete test.zip;*
25 | $exit
26 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/miniunzip.1:
--------------------------------------------------------------------------------
1 | .\" Hey, EMACS: -*- nroff -*-
2 | .TH miniunzip 1 "Nov 7, 2001"
3 | .\" Please adjust this date whenever revising the manpage.
4 | .\"
5 | .\" Some roff macros, for reference:
6 | .\" .nh disable hyphenation
7 | .\" .hy enable hyphenation
8 | .\" .ad l left justify
9 | .\" .ad b justify to both left and right margins
10 | .\" .nf disable filling
11 | .\" .fi enable filling
12 | .\" .br insert line break
13 | .\" .sp insert n+1 empty lines
14 | .\" for manpage-specific macros, see man(7)
15 | .SH NAME
16 | miniunzip - uncompress and examine ZIP archives
17 | .SH SYNOPSIS
18 | .B miniunzip
19 | .RI [ -exvlo ]
20 | zipfile [ files_to_extract ] [-d tempdir]
21 | .SH DESCRIPTION
22 | .B minizip
23 | is a simple tool which allows the extraction of compressed file
24 | archives in the ZIP format used by the MS-DOS utility PKZIP. It was
25 | written as a demonstration of the
26 | .IR zlib (3)
27 | library and therefore lack many of the features of the
28 | .IR unzip (1)
29 | program.
30 | .SH OPTIONS
31 | A number of options are supported. With the exception of
32 | .BI \-d\ tempdir
33 | these must be supplied before any
34 | other arguments and are:
35 | .TP
36 | .BI \-l\ ,\ \-\-v
37 | List the files in the archive without extracting them.
38 | .TP
39 | .B \-o
40 | Overwrite files without prompting for confirmation.
41 | .TP
42 | .B \-x
43 | Extract files (default).
44 | .PP
45 | The
46 | .I zipfile
47 | argument is the name of the archive to process. The next argument can be used
48 | to specify a single file to extract from the archive.
49 |
50 | Lastly, the following option can be specified at the end of the command-line:
51 | .TP
52 | .BI \-d\ tempdir
53 | Extract the archive in the directory
54 | .I tempdir
55 | rather than the current directory.
56 | .SH SEE ALSO
57 | .BR minizip (1),
58 | .BR zlib (3),
59 | .BR unzip (1).
60 | .SH AUTHOR
61 | This program was written by Gilles Vollant. This manual page was
62 | written by Mark Brown . The -d tempdir option
63 | was added by Dirk Eddelbuettel .
64 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/minizip.1:
--------------------------------------------------------------------------------
1 | .\" Hey, EMACS: -*- nroff -*-
2 | .TH minizip 1 "May 2, 2001"
3 | .\" Please adjust this date whenever revising the manpage.
4 | .\"
5 | .\" Some roff macros, for reference:
6 | .\" .nh disable hyphenation
7 | .\" .hy enable hyphenation
8 | .\" .ad l left justify
9 | .\" .ad b justify to both left and right margins
10 | .\" .nf disable filling
11 | .\" .fi enable filling
12 | .\" .br insert line break
13 | .\" .sp insert n+1 empty lines
14 | .\" for manpage-specific macros, see man(7)
15 | .SH NAME
16 | minizip - create ZIP archives
17 | .SH SYNOPSIS
18 | .B minizip
19 | .RI [ -o ]
20 | zipfile [ " files" ... ]
21 | .SH DESCRIPTION
22 | .B minizip
23 | is a simple tool which allows the creation of compressed file archives
24 | in the ZIP format used by the MS-DOS utility PKZIP. It was written as
25 | a demonstration of the
26 | .IR zlib (3)
27 | library and therefore lack many of the features of the
28 | .IR zip (1)
29 | program.
30 | .SH OPTIONS
31 | The first argument supplied is the name of the ZIP archive to create or
32 | .RI -o
33 | in which case it is ignored and the second argument treated as the
34 | name of the ZIP file. If the ZIP file already exists it will be
35 | overwritten.
36 | .PP
37 | Subsequent arguments specify a list of files to place in the ZIP
38 | archive. If none are specified then an empty archive will be created.
39 | .SH SEE ALSO
40 | .BR miniunzip (1),
41 | .BR zlib (3),
42 | .BR zip (1).
43 | .SH AUTHOR
44 | This program was written by Gilles Vollant. This manual page was
45 | written by Mark Brown .
46 |
47 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/minizip.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@prefix@
2 | exec_prefix=@exec_prefix@
3 | libdir=@libdir@
4 | includedir=@includedir@/minizip
5 |
6 | Name: minizip
7 | Description: Minizip zip file manipulation library
8 | Requires:
9 | Version: @PACKAGE_VERSION@
10 | Libs: -L${libdir} -lminizip
11 | Libs.private: -lz
12 | Cflags: -I${includedir}
13 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/minizip/mztools.h:
--------------------------------------------------------------------------------
1 | /*
2 | Additional tools for Minizip
3 | Code: Xavier Roche '2004
4 | License: Same as ZLIB (www.gzip.org)
5 | */
6 |
7 | #ifndef _zip_tools_H
8 | #define _zip_tools_H
9 |
10 | #ifdef __cplusplus
11 | extern "C" {
12 | #endif
13 |
14 | #ifndef _ZLIB_H
15 | #include "zlib.h"
16 | #endif
17 |
18 | #include "unzip.h"
19 |
20 | /* Repair a ZIP file (missing central directory)
21 | file: file to recover
22 | fileOut: output file after recovery
23 | fileOutTmp: temporary file name used for recovery
24 | */
25 | extern int ZEXPORT unzRepair(const char* file,
26 | const char* fileOut,
27 | const char* fileOutTmp,
28 | uLong* nRecovered,
29 | uLong* bytesRecovered);
30 |
31 |
32 | #ifdef __cplusplus
33 | }
34 | #endif
35 |
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/tmpfileplus/Makefile:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | #
3 | # Simplied Makefile to build tmpfileplus for the libxlsxwriter library.
4 | #
5 |
6 | # Keep the output quiet by default.
7 | Q=@
8 | ifdef V
9 | Q=
10 | endif
11 |
12 | UNAME := $(shell uname)
13 |
14 | # Check for MinGW/MinGW64/Cygwin environments.
15 | ifneq (,$(findstring MINGW, $(UNAME)))
16 | MING_LIKE = y
17 | endif
18 | ifneq (,$(findstring MSYS, $(UNAME)))
19 | MING_LIKE = y
20 | endif
21 | ifneq (,$(findstring CYGWIN, $(UNAME)))
22 | MING_LIKE = y
23 | endif
24 |
25 | FPIC = -fPIC
26 |
27 | # Change make options on MinGW/MinGW64/Cygwin.
28 | ifdef MING_LIKE
29 | FPIC =
30 | CC = gcc
31 | endif
32 |
33 | all: tmpfileplus.o tmpfileplus.so
34 |
35 | %.o : %.c
36 | $(Q)$(CC) -c $(CFLAGS) $(TARGET_ARCH) $<
37 |
38 | %.so : %.c
39 | $(Q)$(CC) $(FPIC) -c $(CFLAGS) $(TARGET_ARCH) $< -o $@
40 |
41 | clean:
42 | $(Q)rm -f *.o *.so
43 |
--------------------------------------------------------------------------------
/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.h:
--------------------------------------------------------------------------------
1 | /* $Id: tmpfileplus.h $ */
2 | /*
3 | * $Date: 2016-06-01 03:31Z $
4 | * $Revision: 2.0.0 $
5 | * $Author: dai $
6 | */
7 |
8 | /*
9 | * This Source Code Form is subject to the terms of the Mozilla Public
10 | * License, v. 2.0. If a copy of the MPL was not distributed with this
11 | * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 | *
13 | * Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd
14 | * .
15 | */
16 |
17 | #if _MSC_VER > 1000
18 | #pragma once
19 | #endif
20 |
21 | #ifndef TMPFILEPLUS_H_
22 | #define TMPFILEPLUS_H_
23 |
24 | #include
25 |
26 | /** Create a unique temporary file.
27 | @param dir (optional) directory to create file. If NULL use default TMP directory.
28 | @param prefix (optional) prefix for file name. If NULL use "tmp.".
29 | @param pathname (optional) pointer to a buffer to receive the temp filename.
30 | Allocated using `malloc()`; user to free. Ignored if NULL.
31 | @param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing.
32 | Otherwise file is automatically deleted when closed.
33 | @return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error.
34 | @exception ENOMEM Not enough memory to allocate filename.
35 | */
36 | FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep);
37 |
38 |
39 | /** Create a unique temporary file with filename stored in a fixed-length buffer.
40 | @param dir (optional) directory to create file. If NULL use default directory.
41 | @param prefix (optional) prefix for file name. If NULL use "tmp.".
42 | @param pathnamebuf (optional) buffer to receive full pathname of temporary file. Ignored if NULL.
43 | @param pathsize Size of buffer to receive filename and its terminating null character.
44 | @param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing.
45 | Otherwise file is automatically deleted when closed.
46 | @return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error.
47 | @exception E2BIG Resulting filename is too big for the buffer `pathnamebuf`.
48 | */
49 | FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep);
50 |
51 | #define TMPFILE_KEEP 1
52 |
53 | #endif /* end TMPFILEPLUS_H_ */
54 |
--------------------------------------------------------------------------------
/libxlsxwriter/version.txt:
--------------------------------------------------------------------------------
1 | 2023-12-29 19:18:35 +0700 e3ede9d
--------------------------------------------------------------------------------
/sonar-project.properties:
--------------------------------------------------------------------------------
1 | sonar.sources=.
2 | sonar.language=ruby
3 | sonar.ruby.coverage.reportPaths=coverage/.resultset.json
4 | sonar.exclusions=**/*_test.rb,**/coverage/**
5 |
--------------------------------------------------------------------------------
/test/auto_width_test.rb:
--------------------------------------------------------------------------------
1 | require_relative 'test_helper'
2 |
3 | describe "FastExcel text_width" do
4 |
5 | it "should calculate text width" do
6 | workbook = FastExcel.open(constant_memory: false)
7 | sheet = workbook.add_worksheet
8 | sheet.auto_width = true
9 |
10 | sheet.append_row([
11 | "tini",
12 | "Longer",
13 | "Some longer text!",
14 | "This gem is FFI binding for libxlsxwriter C library"
15 | ])
16 |
17 | assert_equal(sheet.calculated_column_widths, {0 => 3.52, 1 => 5.28, 2 => 14.96, 3 => 44.88})
18 | end
19 |
20 | it "should set the default column width for an empty column on close" do
21 | workbook = FastExcel.open(constant_memory: false)
22 | sheet = workbook.add_worksheet
23 | sheet.auto_width = true
24 |
25 | sheet.append_row([
26 | nil,
27 | "tini",
28 | "Longer",
29 | "Some longer text!",
30 | "This gem is FFI binding for libxlsxwriter C library"
31 | ])
32 |
33 | assert_equal(sheet.calculated_column_widths, {0 => nil, 1 => 3.52, 2 => 5.28, 3 => 14.96, 4 => 44.88})
34 |
35 | workbook.close
36 |
37 | assert_equal(sheet.calculated_column_widths, {0 => FastExcel::DEF_COL_WIDTH, 1 => 3.52, 2 => 5.28, 3 => 14.96, 4 => 44.88})
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/test/date_test.rb:
--------------------------------------------------------------------------------
1 | require_relative 'test_helper'
2 |
3 | describe "FastExcel.date_num" do
4 |
5 | it "should save correct date" do
6 | workbook = FastExcel.open("test.xlsx", constant_memory: true)
7 | worksheet = workbook.add_worksheet("Payments Report")
8 |
9 | date_format = workbook.number_format("[$-409]m/d/yy h:mm AM/PM;@")
10 | worksheet.set_column(0, 0, 20, date_format)
11 |
12 | date = DateTime.parse('2017-03-01 15:15:15 +0000').to_time
13 |
14 | worksheet.write_number(0, 0, FastExcel.date_num(date), nil)
15 | workbook.close
16 |
17 | data = parse_xlsx_as_matrix("test.xlsx")
18 |
19 | assert_equal(data[0][0].to_time, date)
20 | end
21 |
22 | end
23 |
24 | describe "FastExcel.write_value" do
25 |
26 | it "should save correct datetime" do
27 | workbook = FastExcel.open(constant_memory: true)
28 | worksheet = workbook.add_worksheet
29 |
30 | format = workbook.number_format("yyyy-mm-dd hh:mm:ss")
31 | value = DateTime.parse('2017-03-01 15:15:15 +0000')
32 |
33 | worksheet.write_value(0, 0, value, format)
34 | workbook.close
35 |
36 | data = parse_xlsx_as_matrix(workbook.filename)
37 |
38 | assert_equal(data[0][0], value)
39 | end
40 |
41 | it "should save correct date" do
42 | workbook = FastExcel.open(constant_memory: true)
43 | worksheet = workbook.add_worksheet
44 |
45 | format = workbook.number_format("yyyy-mm-dd")
46 | value = Date.parse('2017-03-01')
47 |
48 | worksheet.write_value(0, 0, value, format)
49 | workbook.close
50 |
51 | data = parse_xlsx_as_matrix(workbook.filename)
52 |
53 | assert_equal(data[0][0], value)
54 | end
55 |
56 | end
57 |
--------------------------------------------------------------------------------
/test/default_format_test.rb:
--------------------------------------------------------------------------------
1 | require_relative 'test_helper'
2 |
3 | describe "FastExcel default_format" do
4 |
5 | it "should set default format values on init" do
6 | workbook = FastExcel.open(default_format: {
7 | font_size: 17,
8 | font_family: "ArialFoo",
9 | bold: true
10 | })
11 |
12 | # FastExcel.print_ffi_obj(workbook.default_format)
13 |
14 | assert_equal("ArialFoo", workbook.default_format.font_family)
15 | assert_equal(17, workbook.default_format.font_size)
16 | assert_equal(1, workbook.default_format.bold)
17 | end
18 |
19 | end
20 |
--------------------------------------------------------------------------------
/test/format_test.rb:
--------------------------------------------------------------------------------
1 | require_relative 'test_helper'
2 |
3 | describe "FastExcel::FormatExt align" do
4 |
5 | before do
6 | @workbook = FastExcel.open(constant_memory: true)
7 | @format = @workbook.add_format
8 | end
9 |
10 | it "should give default aligns" do
11 | assert_equal({horizontal: :align_none, vertical: :align_none}, @format.align)
12 | end
13 |
14 | it "should set align by full name" do
15 | @format.align = :align_center
16 | assert_equal({horizontal: :align_center, vertical: :align_none}, @format.align)
17 | end
18 |
19 | it "should set by string" do
20 | @format.align = "align_center"
21 | assert_equal({horizontal: :align_center, vertical: :align_none}, @format.align)
22 | end
23 |
24 | it "should set by short name" do
25 | @format.align = :center
26 | assert_equal({horizontal: :align_center, vertical: :align_none}, @format.align)
27 | end
28 |
29 | it "should set by hash" do
30 | @format.align = {v: "center", h: "center"}
31 | assert_equal({horizontal: :align_center, vertical: :align_vertical_center}, @format.align)
32 | end
33 |
34 | it "should raise exception for unknown value" do
35 | error = assert_raises(ArgumentError) do
36 | @format.align = :aaa
37 | end
38 |
39 | assert_equal(error.message, "Can not set align = :aaa, possible values are: [:align_none, :align_left, "\
40 | ":align_center, :align_right, :align_fill, :align_justify, :align_center_across, :align_distributed, "\
41 | ":align_vertical_top, :align_vertical_bottom, :align_vertical_center, :align_vertical_justify, :align_vertical_distributed]")
42 | end
43 |
44 | it "should raise exception for unknown hash key" do
45 | error = assert_raises(ArgumentError) do
46 | @format.align = {aaa: 1}
47 | end
48 |
49 | assert_equal(error.message, "Not allowed keys for align: [:aaa], possible keys: [:horizontal, :h, :vertical, :v]")
50 | end
51 |
52 | it "should get and set" do
53 | @format.align = {h: :center, v: :center}
54 | format2 = @workbook.add_format(align: @format.align)
55 |
56 | assert_equal({horizontal: :align_center, vertical: :align_vertical_center}, format2.align)
57 | end
58 |
59 | end
60 |
61 |
62 | describe "FastExcel::FormatExt colors" do
63 |
64 | before do
65 | workbook = FastExcel.open(constant_memory: true)
66 | @format = workbook.add_format
67 | end
68 |
69 | it "should set font color as hex num" do
70 | @format.font_color = 0xFF0000
71 | assert_equal(0xFF0000, @format.font_color)
72 | end
73 |
74 | it "should set font color as hex string" do
75 | @format.font_color = '0xFF0000'
76 | assert_equal(0xFF0000, @format.font_color)
77 | end
78 |
79 | it "should set font color as css hex string" do
80 | @format.font_color = '#FF0000'
81 | assert_equal(0xFF0000, @format.font_color)
82 | end
83 |
84 | it "should set font color as short hex string" do
85 | @format.font_color = 'FF0000'
86 | assert_equal(0xFF0000, @format.font_color)
87 | end
88 |
89 | it "should set font color as name" do
90 | @format.font_color = 'red'
91 | assert_equal(0xFF0000, @format.font_color)
92 | end
93 |
94 | it "should set font css color" do
95 | @format.font_color = 'alice_blue'
96 | assert_equal(0xF0F8FF, @format.font_color)
97 | end
98 |
99 | it "should allow to use symbol" do
100 | @format.font_color = :alice_blue
101 | assert_equal(0xF0F8FF, @format.font_color)
102 | end
103 |
104 | it "should have long method for border colors" do
105 | @format.border_bottom_color = :alice_blue
106 | assert_equal(0xF0F8FF, @format.border_bottom_color)
107 | assert_equal(0xF0F8FF, @format.bottom_color)
108 | end
109 |
110 | it "should raise for unexpected type" do
111 | error = assert_raises(ArgumentError) do
112 | @format.font_color = {aaa: 1}
113 | end
114 |
115 | if error.message =~ /=>/
116 | assert_equal(error.message, "Can not use Hash ({:aaa=>1}) for color value, expected String or Hex Number")
117 | else
118 | assert_equal(error.message, "Can not use Hash ({aaa: 1}) for color value, expected String or Hex Number")
119 | end
120 | end
121 |
122 | it "should raise for unexpected color" do
123 | error = assert_raises(ArgumentError) do
124 | @format.font_color = :aaa
125 | end
126 |
127 | assert_equal(error.message, "Unknown color value :aaa, expected hex string or color name")
128 | end
129 |
130 | end
131 |
132 |
133 | describe "FastExcel::FormatExt border" do
134 |
135 | before do
136 | workbook = FastExcel.open(constant_memory: true)
137 | @format = workbook.add_format
138 | end
139 |
140 | it "should set border as symbol" do
141 | @format.bottom = :border_thin
142 | assert_equal(:border_thin, @format.bottom)
143 | end
144 |
145 | it "should set border as short symbol" do
146 | @format.bottom = :thin
147 | assert_equal(:border_thin, @format.bottom)
148 | end
149 |
150 | it "should set border as string" do
151 | @format.bottom = "thin"
152 | assert_equal(:border_thin, @format.bottom)
153 | end
154 |
155 | it "should set border as number" do
156 | @format.bottom = 1
157 | assert_equal(:border_thin, @format.bottom)
158 | end
159 |
160 | it "should set border with long prop name" do
161 | error = assert_raises(ArgumentError) do
162 | @format.border_bottom = :aaa
163 | end
164 |
165 | assert_equal(error.message, "Unknown value :aaa for border. Possible values: "\
166 | "[:none, :thin, :medium, :dashed, :dotted, :thick, :double, :hair, :medium_dashed, "\
167 | ":dash_dot, :medium_dash_dot, :dash_dot_dot, :medium_dash_dot_dot, :slant_dash_dot]")
168 | end
169 |
170 | it "should get value with long name" do
171 | @format.bottom = "thin"
172 | assert_equal(:border_thin, @format.border_bottom)
173 | end
174 |
175 | it "should define aliases" do
176 | @format.font_size = 20
177 | assert_equal(@format.font_size, 20)
178 |
179 | @format.font_name = "XXX"
180 | assert_equal(@format.font_name, "XXX")
181 | end
182 |
183 | end
184 |
--------------------------------------------------------------------------------
/test/reopen_test.rb:
--------------------------------------------------------------------------------
1 | require_relative 'test_helper'
2 |
3 | describe "FastExcel::Worksheet" do
4 |
5 | it "should get_worksheet_by_name" do
6 | workbook = FastExcel.open(constant_memory: false)
7 | workbook.add_worksheet("Page1")
8 |
9 | ws = workbook.get_worksheet_by_name("Page1")
10 | ws.write_row(0, ['1'])
11 |
12 | workbook.close
13 |
14 | error = assert_raises do
15 | FastExcel.open(workbook.filename, constant_memory: false)
16 | end
17 |
18 | assert_equal(error.class, ArgumentError)
19 | assert_equal(error.message, "File '#{workbook.filename}' already exists. FastExcel can not open existing files, only create new files")
20 | end
21 |
22 | end
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | require "simplecov"
2 |
3 | SimpleCov.start do
4 | add_filter 'test'
5 | end
6 |
7 | require 'bundler/setup'
8 | require 'minitest/autorun'
9 | require "minitest/reporters"
10 | require 'pp'
11 | require 'date'
12 |
13 |
14 | Minitest::Reporters.use!(
15 | Minitest::Reporters::DefaultReporter.new(color: true)
16 | )
17 |
18 | require_relative '../lib/fast_excel'
19 |
20 | def parse_xlsx(file_path)
21 | require 'roo'
22 | Roo::Excelx.new(file_path)
23 | ensure
24 | File.delete(file_path)
25 | end
26 |
27 | def get_arrays(workbook)
28 | workbook.close
29 | parse_xlsx_as_matrix(workbook.filename)
30 | end
31 |
32 | def parse_xlsx_as_array(file_path)
33 | data = parse_xlsx_as_matrix(file_path)
34 | headers = data.shift
35 |
36 | data.map do |row|
37 | Hash[ [headers, row].transpose ]
38 | end
39 | end
40 |
41 | def parse_xlsx_as_matrix(file_path)
42 | excel = parse_xlsx(file_path)
43 |
44 | sheet = excel.sheet(0)
45 |
46 | rows = []
47 | if sheet.last_row
48 | 1.upto(sheet.last_row) do |row_number|
49 | row = 1.upto(sheet.last_column).map do |col|
50 | sheet.cell(row_number, col)
51 | end
52 |
53 | rows << row
54 | end
55 | end
56 |
57 | return rows
58 | end
59 |
--------------------------------------------------------------------------------
/test/tmpfile_test.rb:
--------------------------------------------------------------------------------
1 | require_relative 'test_helper'
2 |
3 | describe "FastExcel" do
4 |
5 | it "should create temporary file if filename is nil" do
6 | workbook = FastExcel.open(constant_memory: true)
7 |
8 | assert(workbook.tmp_file)
9 | assert_match(/fast_excel.xlsx$/, workbook.filename)
10 |
11 | result = workbook.read_string
12 | assert(result.size > 1000)
13 | end
14 |
15 | it "should close workbook and delete tmp file when read_string" do
16 | workbook = FastExcel.open
17 | workbook.read_string
18 |
19 | refute(File.exist?(workbook.filename))
20 | refute(File.exist?(File.dirname(workbook.filename)))
21 | refute(workbook.is_open)
22 | end
23 |
24 | end
25 |
--------------------------------------------------------------------------------
/test/validations_test.rb:
--------------------------------------------------------------------------------
1 | require_relative 'test_helper'
2 |
3 | describe "FastExcel validations" do
4 |
5 | it "should raise error when duplicate sheet name" do
6 | workbook = FastExcel.open(constant_memory: true)
7 |
8 | workbook.add_worksheet("Payments Report")
9 | error = assert_raises do
10 | workbook.add_worksheet("Payments Report")
11 | end
12 |
13 | assert_equal(ArgumentError, error.class)
14 | assert_equal("Invalid worksheet name 'Payments Report': (17 - error_sheetname_already_used) Worksheet name is already in use.", error.message)
15 | end
16 |
17 | it "should not raise error when worksheet name is null" do
18 | workbook = FastExcel.open(constant_memory: true)
19 |
20 | ws1 = workbook.add_worksheet()
21 | ws2 = workbook.add_worksheet()
22 | ws2.write_value(0, 2, "aaa")
23 |
24 | assert_equal("Sheet1", ws1[:name])
25 | assert_equal("Sheet2", ws2[:name])
26 | end
27 |
28 | it "should raise error when the sheet name exceeds maximum length" do
29 | workbook = FastExcel.open(constant_memory: true)
30 |
31 | error = assert_raises do
32 | workbook.add_worksheet("ABCDEFGHIJKLMNOPQRSTUVWXYZ012345")
33 | end
34 |
35 | assert_equal(ArgumentError, error.class)
36 | assert_equal("Invalid worksheet name 'ABCDEFGHIJKLMNOPQRSTUVWXYZ012345': (14 - error_sheetname_length_exceeded) Worksheet name exceeds Excel's limit of 31 characters.", error.message)
37 | end
38 |
39 | it "should not raise error when the sheet name is at maximum length" do
40 | workbook = FastExcel.open(constant_memory: true)
41 |
42 | worksheet = workbook.add_worksheet("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234")
43 | worksheet.append_row(["aaa", "bbb", "ccc"])
44 |
45 | assert_equal("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234", worksheet[:name])
46 | end
47 |
48 | it "should validate using Libxlsxwriter validation" do
49 | workbook = FastExcel.open(constant_memory: true)
50 | error = assert_raises do
51 | worksheet = workbook.add_worksheet('a?')
52 | worksheet.write_value(1, 1, 'a') # without the validation, this method will crash the process
53 | end
54 |
55 | assert_equal(ArgumentError, error.class)
56 | assert_equal("Invalid worksheet name 'a?': (15 - error_invalid_sheetname_character) Worksheet name cannot contain invalid characters: '[ ] : * ? / \\'", error.message)
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/test/worksheet_test.rb:
--------------------------------------------------------------------------------
1 | require_relative 'test_helper'
2 |
3 | describe "FastExcel::WorksheetExt append_row" do
4 |
5 | before do
6 | @workbook = FastExcel.open(constant_memory: false)
7 | @worksheet = @workbook.add_worksheet
8 | end
9 |
10 | it "should have last_row_number = -1" do
11 | assert_equal(-1, @worksheet.last_row_number)
12 | end
13 |
14 | it "should write_value and update last_row_number" do
15 | @worksheet.write_value(0, 2, "aaa")
16 | assert_equal(0, @worksheet.last_row_number)
17 | assert_equal([[nil, nil, "aaa"]], get_arrays(@workbook))
18 | end
19 |
20 | it "should append row and update last_row_number" do
21 | @worksheet.append_row(["aaa", "bbb", "ccc"])
22 | @worksheet.append_row(["ddd", "eee", "fff"])
23 |
24 | assert_equal(1, @worksheet.last_row_number)
25 | assert_equal([["aaa", "bbb", "ccc"], ["ddd", "eee", "fff"]], get_arrays(@workbook))
26 | end
27 |
28 | it "should write_row then append and update last_row_number" do
29 | @worksheet.write_row(3, ["aaa", "bbb", "ccc"])
30 | @worksheet.append_row(["ddd", "eee", "fff"])
31 |
32 | assert_equal(4, @worksheet.last_row_number)
33 | assert_equal(
34 | [
35 | [nil, nil, nil],
36 | [nil, nil, nil],
37 | [nil, nil, nil],
38 | ["aaa", "bbb", "ccc"],
39 | ["ddd", "eee", "fff"]
40 | ],
41 | get_arrays(@workbook)
42 | )
43 | end
44 |
45 | it "should not reduce last_row_number" do
46 | @worksheet.append_row(["aaa", "bbb", "ccc"])
47 | @worksheet.append_row(["ddd", "eee", "fff"])
48 | @worksheet.write_value(0, 4, "foo")
49 | @worksheet.append_row(["111", "222", "333"])
50 |
51 | assert_equal(2, @worksheet.last_row_number)
52 | assert_equal(
53 | [
54 | ["aaa", "bbb", "ccc", nil, "foo"],
55 | ["ddd", "eee", "fff", nil, nil],
56 | ["111", "222", "333", nil, nil]
57 | ],
58 | get_arrays(@workbook)
59 | )
60 | end
61 |
62 | it "should not allow to write rows that already saved" do
63 | @workbook = FastExcel.open(constant_memory: true)
64 | @worksheet = @workbook.add_worksheet
65 |
66 | @worksheet.append_row(["aaa", "bbb", "ccc"])
67 | @worksheet.append_row(["ddd", "eee", "fff"])
68 |
69 | error = assert_raises(ArgumentError) do
70 | @worksheet.write_value(0, 4, "foo")
71 | end
72 |
73 | assert_equal("Can not write to saved row in constant_memory mode (attempted row: 0, last saved row: 1)", error.message)
74 | end
75 |
76 | it "should write bigdecimal as a number" do
77 | require 'bigdecimal'
78 |
79 | @workbook = FastExcel.open(constant_memory: true)
80 | @worksheet = @workbook.add_worksheet
81 |
82 | @worksheet.append_row([BigDecimal("0.1234")])
83 |
84 | assert_equal([[0.1234]], get_arrays(@workbook))
85 | end
86 |
87 | it "should set name correctly" do
88 | workbook = FastExcel.open(constant_memory: true)
89 | ws1 = workbook.add_worksheet("foo")
90 | ws2 = workbook.add_worksheet("")
91 |
92 | assert_equal("foo", ws1[:name])
93 | assert_equal("", ws2[:name])
94 | end
95 |
96 | it "should map fields correctly" do
97 | workbook = FastExcel.open(constant_memory: true)
98 |
99 | ws = workbook.add_worksheet("1 should map fields correctly")
100 |
101 | ws.set_right_to_left
102 |
103 | assert_equal(ws[:right_to_left], 1)
104 |
105 | ws = workbook.add_worksheet
106 | ws.center_vertically
107 | assert_equal(ws[:print_options_changed], 1)
108 | assert_equal(ws[:vcenter], 1)
109 |
110 | ws = workbook.add_worksheet
111 | ws.print_row_col_headers
112 | assert_equal(ws[:print_headers], 1)
113 | assert_equal(ws[:print_options_changed], 1)
114 |
115 | ws = workbook.add_worksheet
116 | ws.set_margins(1.5, 2.5, 3.5, 4.5)
117 | assert_equal(ws[:margin_left], 1.5)
118 | assert_equal(ws[:margin_right], 2.5)
119 | assert_equal(ws[:margin_top], 3.5)
120 | assert_equal(ws[:margin_bottom], 4.5)
121 |
122 | assert_equal(ws[:vbreaks_count], 0)
123 |
124 | breaks = [20, 40, 60, 20, 0]
125 | FFI::MemoryPointer.new(:uint16, breaks.size) do |buffer|
126 | buffer.write_array_of_uint16(breaks)
127 | ws.set_v_pagebreaks(buffer)
128 | end
129 |
130 | # FastExcel.print_ffi_obj(ws)
131 |
132 | assert_equal(ws[:vbreaks_count], 4)
133 | end
134 | end
135 |
--------------------------------------------------------------------------------