Initial commit
53
.gitignore
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
*.a
|
||||
*.o
|
||||
*.so
|
||||
*.to
|
||||
*.lo
|
||||
*.la
|
||||
*.dylib
|
||||
test_*
|
||||
!test_*.c
|
||||
!test_*.cpp
|
||||
!test_*.py
|
||||
*.tar.gz
|
||||
*~
|
||||
TAGS
|
||||
.#*
|
||||
*#
|
||||
~*xlsx
|
||||
*.xlsx
|
||||
!test/functional/xlsx_files/*.xlsx
|
||||
*.pyc
|
||||
.cproject
|
||||
.project
|
||||
.pydevproject
|
||||
.settings/
|
||||
.DS_Store
|
||||
__pycache__
|
||||
docs/html
|
||||
docs/latex
|
||||
.deps
|
||||
.dirstamp
|
||||
_temp.c
|
||||
examples/*
|
||||
!examples/*.c
|
||||
!examples/Makefile
|
||||
|
||||
|
||||
third_party/gtest-1.7.0/Makefile
|
||||
third_party/gtest-1.7.0/build-aux/config.h
|
||||
third_party/gtest-1.7.0/build-aux/stamp-h1
|
||||
third_party/gtest-1.7.0/config.log
|
||||
third_party/gtest-1.7.0/config.status
|
||||
third_party/gtest-1.7.0/lib/
|
||||
third_party/gtest-1.7.0/libtool
|
||||
third_party/gtest-1.7.0/scripts/gtest-config
|
||||
|
||||
third_party/zlib-1.2.8/configure.log
|
||||
third_party/zlib-1.2.8/contrib/minizip/miniunz
|
||||
third_party/zlib-1.2.8/contrib/minizip/minizip
|
||||
third_party/zlib-1.2.8/example
|
||||
third_party/zlib-1.2.8/examplesh
|
||||
third_party/zlib-1.2.8/minigzip
|
||||
third_party/zlib-1.2.8/minigzipsh
|
||||
third_party/zlib-1.2.8/zlib.pc
|
70
.indent.pro
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Indent rules for libxlsxwriter.
|
||||
*
|
||||
* The rules for user defined typedefs can be update as follows:
|
||||
*
|
||||
perl -i -pe 'print and last if /[l]ibxlsxwriter typedefs/' .indent.pro
|
||||
ack -h typedef include src | perl -lne 'print "-T $1" if /\w+\s+\w+\s+(\w+)/' | sort >> .indent.pro
|
||||
*
|
||||
*/
|
||||
|
||||
/* Command line options used with GNU indent 2.2.10 */
|
||||
--braces-on-if-line
|
||||
--braces-on-struct-decl-line
|
||||
--case-indentation 4
|
||||
--continue-at-parentheses
|
||||
--declaration-comment-column 0
|
||||
--format-first-column-comments
|
||||
--honour-newlines
|
||||
--ignore-profile
|
||||
--indent-label 0
|
||||
--indent-level 4
|
||||
--no-space-after-function-call-names
|
||||
--no-tabs
|
||||
--swallow-optional-blank-lines
|
||||
|
||||
/* Typedefs used in the code. */
|
||||
-T int8_t
|
||||
-T int16_t
|
||||
-T int32_t
|
||||
-T int64_t
|
||||
-T uint8_t
|
||||
-T uint16_t
|
||||
-T uint32_t
|
||||
-T uint64_t
|
||||
-T ssize_t
|
||||
-T size_t
|
||||
-T time_t
|
||||
|
||||
-T LIST_ENTRY
|
||||
-T SLIST_ENTRY
|
||||
-T STAILQ_ENTRY
|
||||
-T TAILQ_ENTRY
|
||||
|
||||
/* libxlsxwriter typedefs. */
|
||||
-T lxw_app
|
||||
-T lxw_border
|
||||
-T lxw_cell
|
||||
-T lxw_color_t
|
||||
-T lxw_content_types
|
||||
-T lxw_core
|
||||
-T lxw_datetime
|
||||
-T lxw_doc_properties
|
||||
-T lxw_fill
|
||||
-T lxw_font
|
||||
-T lxw_format
|
||||
-T lxw_hash_element
|
||||
-T lxw_hash_table
|
||||
-T lxw_heading_pair
|
||||
-T lxw_packager
|
||||
-T lxw_part_name
|
||||
-T lxw_rel_tuple
|
||||
-T lxw_relationships
|
||||
-T lxw_row
|
||||
-T lxw_sst
|
||||
-T lxw_styles
|
||||
-T lxw_theme
|
||||
-T lxw_tuple
|
||||
-T lxw_workbook
|
||||
-T lxw_worksheet
|
||||
-T lxw_worksheet_init_data
|
10
Changes.txt
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
@page changes Changes
|
||||
|
||||
|
||||
## 0.0.1 June 8 2014
|
||||
|
||||
- First GitHub release.
|
||||
|
||||
|
||||
*/
|
87
LICENSE.txt
Normal file
@ -0,0 +1,87 @@
|
||||
|
||||
Libxlsxwriter is released under a FreeBSD license:
|
||||
|
||||
Copyright (c) 2013, John McNamara <jmcnamara@cpan.org>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
|
||||
|
||||
Libxlsxwriter includes `queue.h` from FreeBSD and the `minizip` component of
|
||||
`zlib` which have the following licenses:
|
||||
|
||||
|
||||
Queue.h from FreeBSD:
|
||||
|
||||
Copyright (c) 1991, 1993
|
||||
The Regents of the University of California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
4. Neither the name of the University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
|
||||
Zlib has the following License/Copyright:
|
||||
|
||||
(C) 1995-2013 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
68
Makefile
Normal file
@ -0,0 +1,68 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Makefile for libxlsxwriter library.
|
||||
#
|
||||
# Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
#
|
||||
|
||||
# Keep the output quiet by default.
|
||||
Q=@
|
||||
ifdef V
|
||||
Q=
|
||||
endif
|
||||
|
||||
.PHONY: docs tags examples
|
||||
|
||||
# Build the libs.
|
||||
all :
|
||||
$(Q)make -C third_party/minizip
|
||||
$(Q)make -C src
|
||||
|
||||
# Build the example programs.
|
||||
examples:
|
||||
$(Q)make -C examples
|
||||
|
||||
# Clean src and test directories.
|
||||
clean :
|
||||
$(Q)make clean -C src
|
||||
$(Q)make clean -C test/unit
|
||||
$(Q)make clean -C test/functional/src
|
||||
$(Q)make clean -C examples
|
||||
$(Q)make clean -C third_party/minizip
|
||||
$(Q)rm -rf docs/html
|
||||
|
||||
# Run the unit tests.
|
||||
test : all test_functional test_unit
|
||||
$(Q)make test -C test/unit
|
||||
|
||||
# Run the functional tests.
|
||||
test_functional : all
|
||||
$(Q)make -C test/functional/src
|
||||
$(Q)py.test test/functional -v
|
||||
|
||||
# Run all tests.
|
||||
test_unit : all
|
||||
@echo "Compiling unit tests ..."
|
||||
$(Q)make test -C test/unit
|
||||
|
||||
# Test the functional test exes with valgrind.
|
||||
test_valgrind : all
|
||||
$(Q)make -C test/functional/src test_valgrind
|
||||
$(Q)make -C examples test_valgrind
|
||||
|
||||
# Indent the source files with the .indent.pro settings.
|
||||
indent:
|
||||
$(Q)gindent src/*.c include/*.h
|
||||
|
||||
tags:
|
||||
$(Q)rm -f TAGS
|
||||
$(Q)etags src/*.c include/*.h include/xlsxwriter/*.h
|
||||
|
||||
# Build the doxygen docs.
|
||||
docs:
|
||||
$(Q)make -C docs
|
||||
|
||||
# Simple minded install.
|
||||
install:
|
||||
$(Q)cp -r include/* /usr/include
|
||||
$(Q)cp lib/* /usr/lib
|
8
Readme.md
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
|
||||
|
||||
The libxlsxwriter library.
|
||||
|
||||
|
||||
Work in Progress. Check back later.
|
||||
|
9
dev/release/fix_dox.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#/bin/bash
|
||||
|
||||
# Perform some minor clean-ups/fixes to the docs.
|
||||
|
||||
perl -i -pe "s/Related Pages/Contents/" html/*.html
|
||||
perl -i -pe "s/Related Pages/Contents/" html/*.html
|
||||
perl -i -pe "s/_page/_8h/" html/pages.html
|
||||
perl -i ../dev/release/fix_example_docs.pl html/examples.html
|
||||
|
75
dev/release/fix_example_docs.pl
Normal file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
#
|
||||
# Simple program to arrange the example programs in a user defined order
|
||||
# instead or sorted order. Also add a caption.
|
||||
#
|
||||
# Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
#
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
# The required example order and descriptions.
|
||||
my @examples = (
|
||||
[ 'hello.c', 'A simple hello world example' ],
|
||||
[ 'anatomy.c', 'The anatomy of a libxlsxwriter program' ],
|
||||
[ 'demo.c', 'Demo of some of the libxlsxwriter features' ],
|
||||
[ 'tutorial1.c', 'Tutorial 1 from the documentation' ],
|
||||
[ 'tutorial2.c', 'Tutorial 2 from the documentation' ],
|
||||
[ 'tutorial3.c', 'Tutorial 3 from the documentation' ],
|
||||
[ 'format_font.c', 'Example of writing data with font formatting' ],
|
||||
[ 'format_num_format.c', 'Example of writing data with number formatting' ],
|
||||
[ 'dates_and_times01.c', 'Writing dates and times with numbers' ],
|
||||
[ 'dates_and_times02.c', 'Writing dates and times with datetime' ],
|
||||
[ 'dates_and_times03.c', 'Dates and times with different formats' ],
|
||||
[ 'utf8.c', 'A example of some UTF-8 text' ],
|
||||
);
|
||||
|
||||
# Convert the array refs to a hash for lookups.
|
||||
my %examples;
|
||||
for my $example (@examples) {
|
||||
$examples{$example->[0]} = 1;
|
||||
}
|
||||
|
||||
my $in_list = 0;
|
||||
|
||||
while ( my $line = <> ) {
|
||||
|
||||
# Print all lines not in the <ul> list.
|
||||
print $line if !$in_list;
|
||||
|
||||
# Check for <ul> list.
|
||||
if ( $line =~ /<div class="textblock">/ ) {
|
||||
$in_list = 1;
|
||||
}
|
||||
|
||||
# Capture the <li> items of the list.
|
||||
if ( $line =~ /<li><a class="el" href="[^"]+">([^<]+)/ ) {
|
||||
my $example = $1;
|
||||
|
||||
# Warn if there are any new/unkown items.
|
||||
if ( !exists $examples{$example} ) {
|
||||
warn "Unknown example: $example\n";
|
||||
}
|
||||
next;
|
||||
}
|
||||
|
||||
# At the end of the <ul> list print out the <li> items in user defined order.
|
||||
if ( $line =~ m{^</ul>} ) {
|
||||
$in_list = 0;
|
||||
|
||||
for my $aref ( @examples ) {
|
||||
my $example = $aref->[0];
|
||||
my $filename = $aref->[0];
|
||||
my $desc = $aref->[1];
|
||||
|
||||
$example =~ s/.c/_8c-example.html/;
|
||||
|
||||
printf qq(<li><a class="el" href="%s">%s</a> %s</li>\n\n),
|
||||
$example, $filename, $desc;
|
||||
}
|
||||
print $line;
|
||||
}
|
||||
}
|
||||
|
||||
__END__
|
2349
docs/Doxyfile
Normal file
177
docs/DoxygenLayout.xml
Normal file
@ -0,0 +1,177 @@
|
||||
<doxygenlayout version="1.0">
|
||||
<!-- Generated by doxygen 1.8.7 -->
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="yes" title=""/>
|
||||
<tab type="modules" visible="yes" title="" intro=""/>
|
||||
<tab type="pages" visible="yes" title="" intro=""/>
|
||||
<tab type="files" visible="yes" title="">
|
||||
<tab type="filelist" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="examples" visible="yes" title="" intro="Example programs using libxlsxwriter:"/>
|
||||
</navindex>
|
||||
|
||||
<!-- Layout definition for a class page -->
|
||||
<class>
|
||||
<briefdescription visible="yes"/>
|
||||
<detaileddescription title=""/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||
<memberdecl>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<publicslots title=""/>
|
||||
<signals title=""/>
|
||||
<publicmethods title=""/>
|
||||
<publicstaticmethods title=""/>
|
||||
<publicattributes title=""/>
|
||||
<publicstaticattributes title=""/>
|
||||
<protectedtypes title=""/>
|
||||
<protectedslots title=""/>
|
||||
<protectedmethods title=""/>
|
||||
<protectedstaticmethods title=""/>
|
||||
<protectedattributes title=""/>
|
||||
<protectedstaticattributes title=""/>
|
||||
<packagetypes title=""/>
|
||||
<packagemethods title=""/>
|
||||
<packagestaticmethods title=""/>
|
||||
<packageattributes title=""/>
|
||||
<packagestaticattributes title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
<privatetypes title=""/>
|
||||
<privateslots title=""/>
|
||||
<privatemethods title=""/>
|
||||
<privatestaticmethods title=""/>
|
||||
<privateattributes title=""/>
|
||||
<privatestaticattributes title=""/>
|
||||
<friends title=""/>
|
||||
<related title="" subtitle=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<allmemberslink visible="yes"/>
|
||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||
<authorsection visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a namespace page -->
|
||||
<namespace>
|
||||
<briefdescription visible="yes"/>
|
||||
<memberdecl>
|
||||
<nestednamespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</namespace>
|
||||
|
||||
<!-- Layout definition for a file page -->
|
||||
<file>
|
||||
<detaileddescription title="Description"/>
|
||||
<sourcelink visible="yes"/>
|
||||
<memberdef>
|
||||
<functions title=""/>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<defines title=""/>
|
||||
<enums title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<memberdecl>
|
||||
<classes visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<variables title=""/>
|
||||
<enums title=""/>
|
||||
<defines title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<authorsection/>
|
||||
</file>
|
||||
|
||||
<!-- Layout definition for a group page -->
|
||||
<group>
|
||||
<briefdescription visible="yes"/>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<memberdecl>
|
||||
<nestedgroups visible="yes" title=""/>
|
||||
<dirs visible="yes" title=""/>
|
||||
<files visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<pagedocs/>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</group>
|
||||
|
||||
<!-- Layout definition for a directory page -->
|
||||
<directory>
|
||||
<briefdescription visible="yes"/>
|
||||
<directorygraph visible="yes"/>
|
||||
<memberdecl>
|
||||
<dirs visible="yes"/>
|
||||
<files visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
</directory>
|
||||
</doxygenlayout>
|
25
docs/Makefile
Normal file
@ -0,0 +1,25 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Makefile for libxlsxwriter library.
|
||||
#
|
||||
# Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
#
|
||||
|
||||
# Keep the output quiet by default.
|
||||
Q=@
|
||||
ifdef V
|
||||
Q=
|
||||
endif
|
||||
|
||||
# Make everything.
|
||||
all : docs
|
||||
|
||||
# Clean up.
|
||||
clean :
|
||||
$(Q)rm -rf html/*
|
||||
|
||||
# Build the doxygen docs.
|
||||
docs:
|
||||
$(Q)doxygen
|
||||
$(Q)../dev/release/fix_dox.sh
|
||||
|
1482
docs/customdoxygen.css
Normal file
BIN
docs/images/anatomy.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
docs/images/date_example01.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
docs/images/date_example02.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
docs/images/date_example03.png
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
docs/images/demo.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
docs/images/format_font.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
docs/images/format_set_font_name.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
docs/images/format_set_num_format.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
docs/images/formats_intro.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
docs/images/formats_set_bg_color.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
docs/images/hello01.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
docs/images/logo.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
docs/images/text_indent.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
docs/images/tutorial01.png
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
docs/images/tutorial02.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
docs/images/tutorial03.png
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
docs/images/utf8.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
docs/images/workbook01.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
docs/images/workbook02.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
docs/images/worksheet02.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
docs/images/write_formula01.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
docs/images/write_number01.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
docs/images/write_number02.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
docs/images/write_string01.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
docs/images/write_string02.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
docs/images/write_string03.png
Normal file
After Width: | Height: | Size: 56 KiB |
19
docs/src/author.dox
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
@page author Author
|
||||
|
||||
Libxlsxwriter was written by John McNamara.
|
||||
|
||||
- [GitHub](https://github.com/jmcnamara)
|
||||
- [Twitter \@jmcnamara13](https://twitter.com/jmcnamara13)
|
||||
|
||||
|
||||
Donations
|
||||
---------
|
||||
|
||||
If you would like to donate to the libxlsxwriter project to keep it active
|
||||
you can do so via
|
||||
[PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ATE9EFWNF7PBJ).
|
||||
|
||||
Next: @ref license
|
||||
|
||||
*/
|
141
docs/src/bugs.dox
Normal file
@ -0,0 +1,141 @@
|
||||
/**
|
||||
|
||||
@page bugs Known Issues and Bugs
|
||||
|
||||
|
||||
This section lists known issues and bugs and gives some information on
|
||||
how to submit bug reports.
|
||||
|
||||
## Content is Unreadable. Open and Repair
|
||||
|
||||
Very, very occasionally you may encounter a bug which generates an Excel
|
||||
warning when opening an `libxlsxwriter` file like:
|
||||
|
||||
> Excel could not open file.xlsx because some content is unreadable. Do
|
||||
> you want to open and repair this workbook.
|
||||
|
||||
This ominous sounding message is Excel's standard warning for any validation
|
||||
error in the XML used for the components of the XLSX file.
|
||||
|
||||
If you encounter an issue like this you should open an issue on GitHub with a
|
||||
program to replicate the issue (see below) or send one of the failing output
|
||||
files to the @ref author.
|
||||
|
||||
## Formulas displayed as `NAME?` until edited
|
||||
|
||||
Excel 2010 and 2013 added functions which weren't defined in the original file
|
||||
specification. These functions are referred to as *future* functions. Examples
|
||||
of these functions are `ACOT`, `CHISQ.DIST.RT` , `CONFIDENCE.NORM`, `STDEV.P`,
|
||||
`STDEV.S` and `WORKDAY.INTL`. The full list is given in the [MS XLSX
|
||||
extensions documentation on future
|
||||
functions](http://msdn.microsoft.com/en-us/library/dd907480%28v=office.12%29.aspx).
|
||||
|
||||
When written using `write_formula()` these functions need to be fully
|
||||
qualified with the `_xlfn.` prefix as they are shown in the MS XLSX
|
||||
documentation link above. For example:
|
||||
|
||||
worksheet_write_formula(worksheet, 0, 0,"=_xlfn.STDEV.S(B1:B10)", NULL);
|
||||
|
||||
|
||||
## Formula results displaying as zero in non-Excel applications
|
||||
|
||||
|
||||
Due to wide range of possible formulas and inter-dependencies between them,
|
||||
`xlsxwriter` doesn't, and realistically cannot, calculate the result of a
|
||||
formula when it is written to an XLSX file. Instead, it stores the value 0 as
|
||||
the formula result. It then sets a global flag in the XLSX file to say that
|
||||
all formulas and functions should be recalculated when the file is opened.
|
||||
|
||||
This is the method recommended in the Excel documentation and in general it
|
||||
works fine with spreadsheet applications. However, applications that don't
|
||||
have a facility to calculate formulas, such as Excel Viewer, or several mobile
|
||||
applications, will only display the 0 results.
|
||||
|
||||
If required, it is also possible to specify the calculated result of the
|
||||
formula using the worksheet_write_formula_num() function.
|
||||
|
||||
|
||||
# Reporting Bugs
|
||||
|
||||
|
||||
Here are some tips on reporting bugs in `libxlsxwriter`.
|
||||
|
||||
## Upgrade to the latest version of the library
|
||||
|
||||
The bug you are reporting may already be fixed in the latest version of
|
||||
the module.
|
||||
|
||||
Check the @ref changes section to see what has changed in the latest
|
||||
versions.
|
||||
|
||||
You can check which version of `libxlsxwriter` that you are using by compiling
|
||||
and running the following program:
|
||||
|
||||
@code
|
||||
#include <stdio.h>
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
printf("Libxlsxwriter version = %s\n", LXW_VERSION);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
## Read the documentation
|
||||
|
||||
Read or search the `libxlsxwriter` documentation to see if the issue you are
|
||||
encountering is already explained.
|
||||
|
||||
|
||||
## Look at the example programs
|
||||
|
||||
There are many @ref examples in the distribution. Try to identify an example
|
||||
program that corresponds to your query and adapt it to use as a bug report.
|
||||
|
||||
## Use the xlsxwriter Issue tracker
|
||||
|
||||
The [libxlsxwriter issue
|
||||
tracker](https://github.com/jmcnamara/libxlsxwriter/issues) is on GitHub.
|
||||
|
||||
|
||||
## Tips for submitting a bug report
|
||||
|
||||
1. Describe the problem as clearly and as concisely as possible.
|
||||
2. Include a sample program. This is probably the most important step.
|
||||
It is generally easier to describe a problem in code than in written
|
||||
prose.
|
||||
3. The sample program should be as small as possible to demonstrate the
|
||||
problem. Don't copy and paste large non-relevant sections of your
|
||||
program.
|
||||
|
||||
A sample bug report is shown below. This format helps analyse and respond to
|
||||
the bug report more quickly.
|
||||
|
||||
Issue with SOMETHING
|
||||
|
||||
I am using libxlsxwriter to do SOMETHING but it appears to do SOMETHING ELSE.
|
||||
|
||||
I am using CC version X.Y.Z, OS = uname and libxlsxwriter x.y.z.
|
||||
|
||||
Here is some code that demonstrates the problem:
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = new_workbook("bug_report.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
worksheet_write_string(worksheet, 0, 0, "Hello", NULL);
|
||||
worksheet_write_number(worksheet, 1, 0, 123, NULL);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
|
||||
|
||||
Next: @ref author "The library author"
|
||||
|
||||
*/
|
495
docs/src/cworkbook.dox
Normal file
@ -0,0 +1,495 @@
|
||||
/**
|
||||
* .. _workbook:
|
||||
*
|
||||
* The Workbook Class
|
||||
* ==================
|
||||
*
|
||||
* The Workbook class is the main class exposed by the xlsxwriter module and it is
|
||||
* the only class that you will need to instantiate directly.
|
||||
*
|
||||
* The Workbook class represents the entire spreadsheet as you see it in Excel and
|
||||
* internally it represents the Excel file as it is written on disk.
|
||||
*
|
||||
* Constructor
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Create a new xlsxwriter Workbook object.
|
||||
*
|
||||
*
|
||||
* @param self Pointer to lxw_format.
|
||||
* @param filename The name of the new Excel file to create.
|
||||
* @param options Optional workbook parameters. See below.
|
||||
* :rtype: A Workbook object.
|
||||
*
|
||||
*
|
||||
* The ``Workbook:new()`` constructor is used to create a new Excel workbook with a
|
||||
* given filename:
|
||||
*
|
||||
* @code
|
||||
* import xlsxwriter
|
||||
*
|
||||
* workbook = xlsxwriter.Workbook('filename.xlsx');
|
||||
* worksheet = workbook:add_worksheet();
|
||||
*
|
||||
* worksheet:write(0, 0, 'Hello Excel');
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @image html workbook01.png
|
||||
*
|
||||
* The constructor options are:
|
||||
*
|
||||
* * **constant_memory**: Reduces the amount of data stored in memory so that
|
||||
* large files can be written efficiently:
|
||||
*
|
||||
* @code
|
||||
* workbook = xlsxwriter.Workbook(filename, {constant_memory = True});
|
||||
*
|
||||
* Note, in this mode a row of data is written and then discarded when a cell
|
||||
* in a new row is added via one of the worksheet ``write_()`` methods.
|
||||
* Therefore, once this mode is active, data should be written in sequential
|
||||
* row order.
|
||||
*
|
||||
* See :ref:`memory_perf` for more details.
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* * **tmpdir**: ``xlsxwriter`` stores worksheet data in a temporary files prior
|
||||
* to assembling the final XLSX file. The temporary files are created in the
|
||||
* system's temp directory. If the default temporary directory isn't accessible
|
||||
* to your application, or doesn't contain enough space, you can specify an
|
||||
* alternative location using the ``tempdir`` option:
|
||||
*
|
||||
* @code
|
||||
* workbook = xlsxwriter.Workbook(filename, {tmpdir = '/home/user/tmp'});
|
||||
*
|
||||
* The temporary directory must exist and will not be created.
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* * **in_memory**: To avoid the use of temporary files in the assembly of the
|
||||
* final XLSX file, for example on servers that don't allow temp files such as
|
||||
* the Google APP Engine, set the ``in_memory`` constructor option to ``True``:
|
||||
*
|
||||
* @code
|
||||
* workbook = xlsxwriter.Workbook(filename, {in_memory = True});
|
||||
*
|
||||
* This option overrides the ``constant_memory`` option.
|
||||
* @endcode
|
||||
*
|
||||
* * **strings_to_numbers**: Enable the
|
||||
* :ref:`worksheet: <Worksheet>`:func:`write()` method to convert strings to
|
||||
* numbers, where possible, using :func:`float()` in order to avoid an Excel
|
||||
* warning about "Numbers Stored as Text". The default is ``False``:
|
||||
*
|
||||
* @code
|
||||
* workbook = xlsxwriter.Workbook(filename, {strings_to_numbers = True});
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* * **strings_to_formulas**: Enable the
|
||||
* :ref:`worksheet: <Worksheet>`:func:`write()` method to convert strings to
|
||||
* formulas. The default is ``True``:
|
||||
*
|
||||
* @code
|
||||
* workbook = xlsxwriter.Workbook(filename, {strings_to_formulas = False});
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* * **strings_to_urls**: Enable the
|
||||
* :ref:`worksheet: <Worksheet>`:func:`write()` method to convert strings to
|
||||
* urls. The default is ``True``:
|
||||
*
|
||||
* @code
|
||||
* workbook = xlsxwriter.Workbook(filename, {strings_to_urls = True});
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* * **default_date_format**: This option is used to specify a default date
|
||||
* format string for use with the
|
||||
* :ref:`worksheet: <Worksheet>`:func:`write_datetime()` method when an
|
||||
* explicit format isn't given. See :ref:`working_with_dates_and_time` for more
|
||||
* details:
|
||||
*
|
||||
* @code
|
||||
* xlsxwriter.Workbook(filename, {default_date_format = 'dd/mm/yy'});
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* * **date_1904**: Excel for Windows uses a default epoch of 1900 and Excel for
|
||||
* Mac uses an epoch of 1904. However, Excel on either platform will convert
|
||||
* automatically between one system and the other. xlsxwriter stores dates in
|
||||
* the 1900 format by default. If you wish to change this you can use the
|
||||
* ``date_1904`` workbook option. This option is mainly for enhanced
|
||||
* compatibility with Excel and in general isn't required very often:
|
||||
*
|
||||
* @code
|
||||
* workbook = xlsxwriter.Workbook(filename, {date_1904 = True});
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* When specifying a filename it is recommended that you use an ``.xlsx``
|
||||
* extension or Excel will generate a warning when opening the file.
|
||||
*
|
||||
* It is possible to write files to in-memory strings using StringIO as follows:
|
||||
*
|
||||
* @code
|
||||
* output = StringIO();
|
||||
* workbook = xlsxwriter.Workbook(output);
|
||||
* worksheet = workbook:add_worksheet();
|
||||
*
|
||||
* worksheet:write('A1', 'Hello');
|
||||
* workbook:close();
|
||||
*
|
||||
* xlsx_data = output.getvalue();
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* To avoid the use of any temporary files and keep the entire file in-memory use
|
||||
* the ``in_memory`` constructor option shown above.
|
||||
*
|
||||
* See also :ref:`ex_http_server`.
|
||||
*
|
||||
*
|
||||
* workbook:add_worksheet()
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Add a new worksheet to a workbook:
|
||||
*
|
||||
*
|
||||
* @param self Pointer to lxw_format.
|
||||
* @param sheetname Optional worksheet name, defaults to Sheet1, etc.
|
||||
* :rtype: A :ref:`worksheet <Worksheet>` object.
|
||||
*
|
||||
* The ``add_worksheet()`` method adds a new worksheet to a workbook:
|
||||
*
|
||||
* At least one worksheet should be added to a new workbook: The
|
||||
* :ref:`Worksheet <worksheet>` object is used to write data and configure a
|
||||
* worksheet in the workbook:
|
||||
*
|
||||
* The ``sheetname`` parameter is optional. If it is not specified the default
|
||||
* Excel convention will be followed, i.e. Sheet1, Sheet2, etc.:
|
||||
*
|
||||
* @code
|
||||
* worksheet1 = workbook:add_worksheet(); // Sheet1
|
||||
* worksheet2 = workbook:add_worksheet('Foglio2'); // Foglio2
|
||||
* worksheet3 = workbook:add_worksheet('Data'); // Data
|
||||
* worksheet4 = workbook:add_worksheet(); // Sheet4
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @image html workbook02.png
|
||||
*
|
||||
* The worksheet name must be a valid Excel worksheet name, i.e. it cannot contain
|
||||
* any of the characters ``' [ ] : * ? / \
|
||||
* '`` and it must be less than 32 characters.
|
||||
*
|
||||
* In addition, you cannot use the same, case insensitive, ``sheetname`` for more
|
||||
* than one worksheet:
|
||||
*
|
||||
* workbook:add_format()
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Create a new Format object to formats cells in worksheets.
|
||||
*
|
||||
*
|
||||
* @param self Pointer to lxw_format.
|
||||
* @paramionary properties An optional dictionary of format properties.
|
||||
* :rtype: A :ref:`format <Format>` object.
|
||||
*
|
||||
* The ``add_format()`` method can be used to create new :ref:`Format <Format>`
|
||||
* objects which are used to apply formatting to a cell. You can either define
|
||||
* the properties at creation time via a dictionary of property values or later
|
||||
* via method calls:
|
||||
*
|
||||
* @code
|
||||
* format1 = workbook:add_format(props); // Set properties at creation.
|
||||
* format2 = workbook:add_format(); // Set properties later.
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* See the :ref:`format` and :ref:`working_with_formats` sections for more details
|
||||
* about Format properties and how to set them.
|
||||
*
|
||||
*
|
||||
* workbook:add_chart()
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Create a chart object that can be added to a worksheet:
|
||||
*
|
||||
*
|
||||
* @param self Pointer to lxw_format.
|
||||
* @paramionary options An dictionary of chart type options.
|
||||
* :rtype: A :ref:`Chart <chart_class>` object.
|
||||
*
|
||||
* This method is use to create a new chart object that can be inserted into a
|
||||
* worksheet via the :func:`insert_chart()` Worksheet method:
|
||||
*
|
||||
* @code
|
||||
* chart = workbook:add_chart({type = 'column'});
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* The properties that can be set are:
|
||||
*
|
||||
* @code
|
||||
* type (required);
|
||||
* subtype (optional);
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* * ``type``
|
||||
*
|
||||
* This is a required parameter. It defines the type of chart that will be
|
||||
* created:
|
||||
*
|
||||
* @code
|
||||
* chart = workbook:add_chart({type = 'line'});
|
||||
*
|
||||
* The available types are:
|
||||
*
|
||||
* @code
|
||||
* area
|
||||
* bar
|
||||
* column
|
||||
* line
|
||||
* pie
|
||||
* radar
|
||||
* scatter
|
||||
* stock
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* * ``subtype``
|
||||
*
|
||||
* Used to define a chart subtype where available:
|
||||
*
|
||||
* @code
|
||||
* workbook:add_chart({type = 'bar', subtype = 'stacked'});
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* See the :ref:`chart_class` for a list of available chart subtypes.
|
||||
*
|
||||
* See also :ref:`working_with_charts` and :ref:`chart_examples`.
|
||||
*
|
||||
* workbook:add_chartsheet()
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Add a new add_chartsheet to a workbook:
|
||||
*
|
||||
*
|
||||
* @param self Pointer to lxw_format.
|
||||
* @param sheetname Optional chartsheet name, defaults to Chart1, etc.
|
||||
* :rtype: A :ref:`chartsheet <Chartsheet>` object.
|
||||
*
|
||||
* The ``add_chartsheet()`` method adds a new chartsheet to a workbook:
|
||||
*
|
||||
* @image html chartsheet.png
|
||||
*
|
||||
* See :ref:`chartsheet` for details.
|
||||
*
|
||||
* The ``sheetname`` parameter is optional. If it is not specified the default
|
||||
* Excel convention will be followed, i.e. Chart1, Chart2, etc.
|
||||
*
|
||||
* The chartsheet name must be a valid Excel worksheet name, i.e. it cannot
|
||||
* contain any of the characters ``' [ ] : * ? / \
|
||||
* '`` and it must be less than 32 characters.
|
||||
*
|
||||
* In addition, you cannot use the same, case insensitive, ``sheetname`` for more
|
||||
* than one chartsheet.
|
||||
*
|
||||
*
|
||||
* workbook:close()
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Close the Workbook object and write the XLSX file.
|
||||
*
|
||||
*
|
||||
* In general your Excel file will be closed automatically when your program ends
|
||||
* or when the Workbook object goes out of scope, however the ``close()`` method
|
||||
* can be used to explicitly close an Excel file:
|
||||
*
|
||||
* @code
|
||||
* workbook:close();
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* An explicit ``close()`` is required if the file must be closed prior to
|
||||
* performing some external action on it such as copying it, reading its size or
|
||||
* attaching it to an email.
|
||||
*
|
||||
* In addition, ``close()`` may occasionally be required to prevent Python's
|
||||
* garbage collector from disposing of the Workbook, Worksheet and Format objects
|
||||
* in the wrong order.
|
||||
*
|
||||
*
|
||||
* workbook:set_properties()
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Set the document properties such as Title, Author etc.
|
||||
*
|
||||
*
|
||||
* @param self Pointer to lxw_format.
|
||||
* @param properties Dictionary of document properties.
|
||||
*
|
||||
* The ``set_properties`` method can be used to set the document properties of the
|
||||
* Excel file created by ``xlsxwriter``. These properties are visible when you
|
||||
* use the ``Office Button -> Prepare -> Properties`` option in Excel and are
|
||||
* also available to external applications that read or index windows files.
|
||||
*
|
||||
* The properties that can be set are:
|
||||
*
|
||||
* * ``title``
|
||||
* * ``subject``
|
||||
* * ``author``
|
||||
* * ``manager``
|
||||
* * ``company``
|
||||
* * ``category``
|
||||
* * ``keywords``
|
||||
* * ``comments``
|
||||
* * ``status``
|
||||
*
|
||||
* The properties are all optional and should be passed in dictionary format as
|
||||
* follows:
|
||||
*
|
||||
* @code
|
||||
* workbook:set_properties({
|
||||
* title = 'This is an example spreadsheet',
|
||||
* subject = 'With document properties',
|
||||
* author = 'John McNamara',
|
||||
* manager = 'Dr. Heinz Doofenshmirtz',
|
||||
* company = 'of Wolves',
|
||||
* category = 'Example spreadsheets',
|
||||
* keywords = 'Sample, Example, Properties',
|
||||
* comments = 'Created with Python and xlsxwriter'});
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @image html doc_properties.png
|
||||
*
|
||||
* See also :ref:`ex_doc_properties`.
|
||||
*
|
||||
* workbook:define_name()
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Create a defined name in the workbook to use as a variable.
|
||||
*
|
||||
*
|
||||
* @param self Pointer to lxw_format.
|
||||
* @param name The defined name.
|
||||
* @param formula The cell or range that the defined name refers to.
|
||||
*
|
||||
* This method is used to defined a name that can be used to represent a value, a
|
||||
* single cell or a range of cells in a workbook: These defined names can then be
|
||||
* used in formulas:
|
||||
*
|
||||
* @code
|
||||
* workbook:define_name('Exchange_rate', '=0.96');
|
||||
* worksheet:write('B3', '=B2*Exchange_rate');
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* As in Excel a name defined like this is "global" to the workbook and can be
|
||||
* referred to from any worksheet:
|
||||
*
|
||||
* @code
|
||||
* // Global workbook name.
|
||||
* workbook:define_name('Sales', '=Sheet1!$G$1:$H$10');
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* It is also possible to define a local/worksheet name by prefixing it with the
|
||||
* sheet name using the syntax ``'sheetname!definedname'``:
|
||||
*
|
||||
* @code
|
||||
* // Local worksheet name.
|
||||
* workbook:define_name('Sheet2!Sales', '=Sheet2!$G$1:$G$10');
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* If the sheet name contains spaces or special characters you must follow the
|
||||
* Excel convention and enclose it in single quotes:
|
||||
*
|
||||
* @code
|
||||
* workbook:define_name("'New Data'!Sales", '=Sheet2!$G$1:$G$10');
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* See also the ``defined_name.py`` program in the examples directory.
|
||||
*
|
||||
*
|
||||
* workbook:worksheets()
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Return a list of the worksheet objects in the workbook:
|
||||
*
|
||||
*
|
||||
* :rtype: A list of :ref:`worksheet <Worksheet>` objects.
|
||||
*
|
||||
* The ``worksheets()`` method returns a list of the worksheets in a workbook:
|
||||
* This is useful if you want to repeat an operation on each worksheet in a
|
||||
* workbook:
|
||||
*
|
||||
* @code
|
||||
* for worksheet in workbook:worksheets():
|
||||
* worksheet:write('A1', 'Hello');
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* workbook:set_calc_mode()
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Set the Excel calculation mode for the workbook:
|
||||
*
|
||||
*
|
||||
* @param self Pointer to lxw_format.
|
||||
* @param mode The calculation mode string
|
||||
*
|
||||
* Set the calculation mode for formulas in the workbook: This is mainly of use
|
||||
* for workbooks with slow formulas where you want to allow the user to calculate
|
||||
* them manually.
|
||||
*
|
||||
* The ``mode`` parameter can be:
|
||||
*
|
||||
* * ``auto``: The default. Excel will re-calculate formulas when a formula or a
|
||||
* value affecting the formula changes.
|
||||
*
|
||||
* * ``auto_except_tables``: Excel will automatically re-calculate formulas
|
||||
* except for tables.
|
||||
*
|
||||
* * ``manual``: Only re-calculate formulas when the user requires it. Generally
|
||||
* by pressing F9.
|
||||
*
|
||||
*
|
||||
* workbook:use_zip64()
|
||||
*/
|
||||
|
||||
*
|
||||
/**
|
||||
* @brief Allow ZIP64 extensions when writing xlsx file zip container.
|
||||
*
|
||||
*
|
||||
* Use ZIP64 extensions when writing the xlsx file zip container and allow files
|
||||
* greater than 4 GB.
|
||||
*
|
2247
docs/src/cworksheet.dox
Normal file
95
docs/src/examples.dox
Normal file
@ -0,0 +1,95 @@
|
||||
/**
|
||||
@page examples Example Programs
|
||||
|
||||
|
||||
@example hello.c
|
||||
The simplest possible program and spreadsheet. This is a good place to
|
||||
start to see if the libxlsxwriter library is installed and working
|
||||
correctly.
|
||||
|
||||
Next example: @ref anatomy.c
|
||||
@image html hello01.png
|
||||
|
||||
|
||||
@example anatomy.c
|
||||
Anatomy of a simple libxlsxwriter program.
|
||||
|
||||
Next example: @ref demo.c
|
||||
@image html anatomy.png
|
||||
|
||||
|
||||
@example demo.c
|
||||
A simple example of some of the features of the libxlsxwriter library.
|
||||
|
||||
Next example: @ref format_font.c
|
||||
@image html demo.png
|
||||
|
||||
|
||||
@example format_font.c
|
||||
Example of writing some data with font formatting to a simple Excel
|
||||
file using libxlsxwriter.
|
||||
|
||||
Next example: @ref format_num_format.c
|
||||
@image html format_font.png
|
||||
|
||||
|
||||
@example format_num_format.c
|
||||
Example of writing some data with numeric formatting to a simple Excel
|
||||
file using libxlsxwriter.
|
||||
|
||||
Next example: @ref tutorial1.c
|
||||
@image html format_set_num_format.png
|
||||
|
||||
|
||||
@example tutorial1.c
|
||||
A tutorial program which is shown, with explanations, in @ref tutorial01.
|
||||
|
||||
Next example: @ref tutorial2.c
|
||||
@image html tutorial01.png
|
||||
|
||||
|
||||
@example tutorial2.c
|
||||
A tutorial program which is shown, with explanations, in @ref tutorial02.
|
||||
|
||||
Next example: @ref tutorial3.c
|
||||
@image html tutorial02.png
|
||||
|
||||
|
||||
@example tutorial3.c
|
||||
A tutorial program which is shown, with explanations, in @ref tutorial03.
|
||||
|
||||
Next example: @ref dates_and_times01.c
|
||||
@image html tutorial03.png
|
||||
|
||||
|
||||
@example dates_and_times01.c Example of writing a dates and time in Excel
|
||||
using a number with date formatting. This demonstrates that dates and times in
|
||||
Excel are just formatted real numbers. An easier approach using a lxw_datetime
|
||||
struct is shown in the next example.
|
||||
|
||||
Next example: @ref dates_and_times02.c.
|
||||
@image html date_example01.png
|
||||
|
||||
|
||||
@example dates_and_times02.c
|
||||
Example of writing dates and times in Excel using an lxw_datetime struct and
|
||||
date formatting.
|
||||
|
||||
Next example: @ref dates_and_times03.c
|
||||
@image html date_example02.png
|
||||
|
||||
|
||||
@example dates_and_times03.c
|
||||
Example of writing dates and times in Excel using different date formats.
|
||||
|
||||
Next example: @ref utf8.c
|
||||
@image html date_example03.png
|
||||
|
||||
|
||||
@example utf8.c
|
||||
A simple Unicode UTF-8 example. Note, the source file is UTF-8 encoded.
|
||||
|
||||
|
||||
@image html utf8.png
|
||||
|
||||
*/
|
67
docs/src/faq.dox
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
|
||||
@page faq Frequently Asked Questions
|
||||
|
||||
The section outlines some answers to some frequently asked questions.
|
||||
|
||||
### Q. Can Libxlsxwriter use an existing Excel file as a template?
|
||||
|
||||
No.
|
||||
|
||||
Libxlsxwriter is designed only as a file *writer*. It cannot read or modify
|
||||
an existing Excel file.
|
||||
|
||||
### Q. Why do my formulas show a zero result in some, non-Excel applications?
|
||||
|
||||
Due to wide range of possible formulas and inter-dependencies between them
|
||||
`libxlsxwriter` doesn't, and realistically cannot, calculate the result of a
|
||||
formula when it is written to an XLSX file. Instead, it stores the value 0 as
|
||||
the formula result. It then sets a global flag in the XLSX file to say that
|
||||
all formulas and functions should be recalculated when the file is opened.
|
||||
|
||||
This is the method recommended in the Excel documentation and in general it
|
||||
works fine with spreadsheet applications. However, applications that don't
|
||||
have a facility to calculate formulas, such as Excel Viewer, or several mobile
|
||||
applications, will only display the 0 results.
|
||||
|
||||
If required, it is also possible to specify the calculated result of the
|
||||
formula using the worksheet_write_formula_num() function.
|
||||
|
||||
|
||||
### Q. Can I apply a format to a range of cells in one go?
|
||||
|
||||
Currently no. However, it is a planned features to allow cell formats
|
||||
and data to be written separately.
|
||||
|
||||
|
||||
### Q. Is Visual C++ on Windows supported?
|
||||
|
||||
There is currently no supplied MSVC project files to build the `libxlsxwriter`
|
||||
library. However, the source code is ANSI C so it should work with current and
|
||||
older versions of MSVC with very minor modifications. (Building the `zlib`
|
||||
dependency should also be possible).
|
||||
|
||||
If you would like to add MSVC support to libxlsxwriter then open a GitHub
|
||||
issue to get a discussion going and send a Pull Request.
|
||||
|
||||
|
||||
### Q. Is feature X supported or will it be supported?
|
||||
|
||||
All supported features are documented. In time the feature set may expand to
|
||||
include more of the functionality of the [Python
|
||||
XlsxWriter](http://xlsxwriter.readthedocs.org) module.
|
||||
|
||||
### Q. Is there an "AutoFit" option for columns?
|
||||
|
||||
Unfortunately, there is no way to specify "AutoFit" for a column in the
|
||||
Excel file format. This feature is only available at runtime from within
|
||||
Excel. It is possible to simulate "AutoFit" by tracking the width of the
|
||||
data in the column as your write it.
|
||||
|
||||
### Q. Do people actually ask these questions frequently, or at all?
|
||||
|
||||
Apart from this question, yes.
|
||||
|
||||
Next: @ref bugs
|
||||
|
||||
*/
|
146
docs/src/getting_started.dox
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
@page getting_started Getting Started with libxlsxwriter
|
||||
|
||||
|
||||
Here are some instructions to get you up and running with the libxlsxwriter
|
||||
library on a Unix system.
|
||||
|
||||
For Windows see the @ref faq "FAQ".
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### Install the dependencies
|
||||
|
||||
There is only one (non-testing) dependency: `zlib`.
|
||||
|
||||
[Zlib](http://www.zlib.net) is required for its shared objects and header
|
||||
files. On a Debian Linux system you can install them using `apt-get` as
|
||||
follows:
|
||||
|
||||
sudo apt-get install -y zlib1g-dev
|
||||
|
||||
On systems without a package manager the following should work:
|
||||
|
||||
curl -O -L http://zlib.net/zlib-1.2.8.tar.gz
|
||||
tar zxf zlib-1.2.8.tar.gz
|
||||
cd zlib-1.2.8
|
||||
|
||||
./configure
|
||||
make
|
||||
|
||||
sudo make install
|
||||
|
||||
### Clone the libxlsxwriter repository
|
||||
|
||||
|
||||
Clone the libxlsxwriter source code repository from GitHub as follows (or
|
||||
using your preferred protocol):
|
||||
|
||||
git clone https://github.com/jmcnamara/libxlsxwriter.git
|
||||
|
||||
If you prefer you can get a tarball of the latest code:
|
||||
|
||||
curl -O -L http://github.com/jmcnamara/libxlsxwriter/archive/master.tar.gz
|
||||
|
||||
### Build the source code
|
||||
|
||||
Build the source code as follows:
|
||||
|
||||
cd libxlsxwriter
|
||||
make
|
||||
|
||||
This will create a static and dynamic library in the local `./lib` directory:
|
||||
|
||||
ls lib
|
||||
libxlsxwriter.a libxlsxwriter.so
|
||||
|
||||
|
||||
### Try an example
|
||||
|
||||
If there weren't any warnings or errors in the previous step (and there
|
||||
shouldn't have been) then you can build the programs in the `examples`
|
||||
directory and try one of them out:
|
||||
|
||||
make examples
|
||||
./examples/hello
|
||||
|
||||
This will create a `hello_world.xlsx` file in your current directory. Open the
|
||||
file as follows, or directly from a spreadsheet application:
|
||||
|
||||
xdg-open hello_world.xlsx # Linux. Usually.
|
||||
open hello_world.xlsx # Mac OS X if Excel is installed.
|
||||
|
||||
The output should look like this: @image html hello01.png
|
||||
|
||||
There is a large range of tests that you can run but they have some additional
|
||||
dependencies. If you are interested see @ref running_the_tests.
|
||||
|
||||
|
||||
### Install the library
|
||||
|
||||
Libxlsxwriter supports a simplified installation scheme for a static and
|
||||
dynamic/shared library and header files. The installation has been tested on
|
||||
Linux and OS X:
|
||||
|
||||
sudo make install
|
||||
|
||||
This isn't fool proof but if it fails on your system you will probably know
|
||||
exactly how to fix it or have no idea how to fix it. I'm hoping for the
|
||||
former.
|
||||
|
||||
## TL;DR
|
||||
|
||||
If you prefer to assemble Ikea furniture first and read the instructions later
|
||||
then the following minimal set of commands should get you up and going on a
|
||||
Debian like system:
|
||||
|
||||
sudo apt-get install -y zlib1g-dev
|
||||
git clone https://github.com/jmcnamara/libxlsxwriter.git
|
||||
cd libxlsxwriter
|
||||
make
|
||||
sudo make install
|
||||
|
||||
# Using the library
|
||||
|
||||
Using you favourite editor Emacs create a file like the following called
|
||||
`myexcel.c`:
|
||||
|
||||
@code
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = new_workbook("myexcel.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
|
||||
worksheet_write_string(worksheet, row, col, "Hello me!", NULL);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
@endcode
|
||||
|
||||
If you executed the `"make install"` command in the previous section then you
|
||||
should be able to compile the program as follows:
|
||||
|
||||
cc myexcel.c -o myexcel -lxlsxwriter
|
||||
|
||||
This will create an executable that you can run to generate an Excel spreadsheet:
|
||||
|
||||
./myexcel
|
||||
xdg-open myexcel.xlsx
|
||||
|
||||
If the installation didn't work for you then you can link against the static
|
||||
library you created in the "Build the source code" step:
|
||||
|
||||
cc myexcel.c -o myexcel -I /path/to/libxlsxwriter/include /path/to/libxlsxwriter/lib/libxlsxwriter.a -lz
|
||||
|
||||
And that's it! In the next sections we will look at some more detailed
|
||||
examples.
|
||||
|
||||
Next: @ref tutorial01
|
||||
|
||||
|
||||
*/
|
37
docs/src/introduction.dox
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
|
||||
@page introduction Introduction
|
||||
|
||||
<b>libxlsxwriter</b> is a C library for writing files in the Excel 2007+ XLSX
|
||||
file format.
|
||||
|
||||
It can be used to write text, numbers, and formulas to multiple
|
||||
worksheets and it supports features such as formatting.
|
||||
|
||||
The main advantages of using `libxlsxwriter` are:
|
||||
|
||||
- It has a high degree of fidelity with files produced by Excel. In
|
||||
most cases the files produced are 100% equivalent to files
|
||||
produced by Excel.
|
||||
- It has extensive documentation, example files and tests.
|
||||
|
||||
However:
|
||||
|
||||
- It can only create **new files**. It cannot read or modify
|
||||
existing files.
|
||||
|
||||
Libxlsxwriter is a C port of the Perl
|
||||
[Excel::Writer::XLSX](http://search.cpan.org/~jmcnamara/Excel-Writer-XLSX/)
|
||||
module and the Python [XlsxWriter](http://xlsxwriter.readthedocs.org) module
|
||||
and is licensed under a FreeBSD @ref license.
|
||||
|
||||
|
||||
@note
|
||||
|
||||
The 0.0.1 version of libxlsxwriter should be considered as a beta. In
|
||||
particular it has some known performance/memory limitations that will be fixed
|
||||
in the next releases.
|
||||
|
||||
Next: @ref getting_started
|
||||
|
||||
*/
|
94
docs/src/license.dox
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
|
||||
@page license License
|
||||
|
||||
Libxlsxwriter is released under a FreeBSD license:
|
||||
|
||||
Copyright (c) 2013, John McNamara <jmcnamara@cpan.org>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
|
||||
|
||||
Libxlsxwriter includes `queue.h` from FreeBSD and the `minizip` component of
|
||||
`zlib` which have the following licenses:
|
||||
|
||||
|
||||
Queue.h from FreeBSD:
|
||||
|
||||
Copyright (c) 1991, 1993
|
||||
The Regents of the University of California. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
4. Neither the name of the University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
|
||||
Zlib has the following License/Copyright:
|
||||
|
||||
(C) 1995-2013 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
|
||||
Next: @ref changes
|
||||
*/
|
43
docs/src/mainpage.dox
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
@mainpage Creating Excel files with C and libxlsxwriter
|
||||
|
||||
<b>Libxlsxwriter</b> is a C library for creating Excel XLSX files.
|
||||
|
||||
@image html demo.png
|
||||
|
||||
@ref demo.c "(Sample code to create the above spreadsheet.)"
|
||||
|
||||
@section mainpage_intro libxlsxwriter
|
||||
|
||||
Libxlsxwriter is a C library that can be used to write text, numbers and
|
||||
formulas to multiple worksheets in an Excel 2007+ XLSX file. It supports
|
||||
features such as:
|
||||
|
||||
- 100% compatible Excel XLSX files
|
||||
- Full formatting
|
||||
- Source code available on [GitHub](https://github.com/jmcnamara/libxlsxwriter)
|
||||
- FreeBSD @ref license
|
||||
- ANSI C
|
||||
- Works with GCC 4.4, 4.6, 4.7, 4.8, tcc and clang
|
||||
- Works on Linux and OS X.
|
||||
- The only dependency is on `zlib`
|
||||
|
||||
This document explains how to use the libxlsxwriter library. See the
|
||||
following sections for more information:
|
||||
|
||||
- @ref introduction
|
||||
- @ref getting_started
|
||||
- @ref tutorial01
|
||||
- @ref tutorial02
|
||||
- @ref tutorial03
|
||||
- @ref workbook.h "The Workbook object"
|
||||
- @ref worksheet.h "The Worksheet object"
|
||||
- @ref format.h "The Format object"
|
||||
- @ref working_with_colors
|
||||
- @ref working_with_dates
|
||||
- @ref examples
|
||||
- @ref author
|
||||
- @ref license
|
||||
- @ref changes
|
||||
|
||||
*/
|
113
docs/src/running_the_tests.dox
Normal file
@ -0,0 +1,113 @@
|
||||
///
|
||||
///@page running_the_tests Running the Test Suite
|
||||
///
|
||||
///
|
||||
///This section shows how to set up and run the test suite for libxlsxwriter.
|
||||
///
|
||||
///## Functional Tests
|
||||
///
|
||||
///The functional tests compare the output from libxlsxwriter against xlsx files
|
||||
///created in Excel.
|
||||
///
|
||||
///
|
||||
///The functional tests use the Python module [pytest](http://pytest.org/) as a
|
||||
///test runner.
|
||||
///
|
||||
///Install the `pytest` module using one of the following methods:
|
||||
///
|
||||
/// sudo apt-get install -y python-pytest
|
||||
/// # or
|
||||
/// sudo easy_install pytest
|
||||
/// # or
|
||||
/// sudo pip install pytest
|
||||
///
|
||||
///The functional tests can then be run:
|
||||
///
|
||||
/// $ cd libxlsxwriter
|
||||
///
|
||||
/// $ make test_functional
|
||||
///
|
||||
/// =========================== test session starts ===========================
|
||||
/// collected 14 items
|
||||
///
|
||||
/// test/functional/test_formatting.py:16: TestCompareXLSXFiles.test_format01 PASSED
|
||||
/// test/functional/test_formatting.py:19: TestCompareXLSXFiles.test_format02 PASSED
|
||||
/// test/functional/test_formatting.py:24: TestCompareXLSXFiles.test_format06 PASSED
|
||||
/// ...
|
||||
/// test/functional/test_write_data.py:25: TestCompareXLSXFiles.test_data04 PASSED
|
||||
/// test/functional/test_write_data.py:28: TestCompareXLSXFiles.test_data05 PASSED
|
||||
/// test/functional/test_write_data.py:31: TestCompareXLSXFiles.test_data06 PASSED
|
||||
/// test/functional/test_write_data.py:34: TestCompareXLSXFiles.test_data07 PASSED
|
||||
/// =========================== 14 passed in 0.41 seconds =====================
|
||||
///
|
||||
///
|
||||
///## Unit Tests
|
||||
///
|
||||
///The unit tests test the components of the library at the level of individual
|
||||
///functions or compilation units.
|
||||
///
|
||||
///The unit tests require the [googletest](https://code.google.com/p/googletest/)
|
||||
///test framework. There isn't a default installation method for `googletest` but
|
||||
///the following method from
|
||||
///[StackOverflow](http://stackoverflow.com/questions/13513905/how-to-properly-setup-googletest-on-linux)
|
||||
///works on Linux and OS X:
|
||||
///
|
||||
/// wget http://googletest.googlecode.com/files/gtest-1.7.0.zip
|
||||
/// unzip gtest-1.7.0.zip
|
||||
/// cd gtest-1.7.0
|
||||
/// ./configure
|
||||
/// make
|
||||
///
|
||||
/// sudo cp -a include/gtest /usr/include
|
||||
/// sudo cp -a lib/.libs/* /usr/lib/
|
||||
///
|
||||
///The unit tests can then be run as follows. Note, the compilation of the unit tests can take some time:
|
||||
///
|
||||
/// $ make test_unit
|
||||
///
|
||||
/// Compiling unit tests ...
|
||||
/// Running main() from gtest_main.cc
|
||||
/// [==========] Running 146 tests from 10 test cases.
|
||||
/// [----------] Global test environment set-up.
|
||||
/// [----------] 9 tests from utility
|
||||
/// [ RUN ] utility._datetime_date_and_time
|
||||
/// [ OK ] utility._datetime_date_and_time (0 ms)
|
||||
/// [ RUN ] utility._datetime_date_only
|
||||
/// [ OK ] utility._datetime_date_only (0 ms)
|
||||
/// ...
|
||||
/// [ RUN ] styles.write_xf33
|
||||
/// [ OK ] styles.write_xf33 (0 ms)
|
||||
/// [ RUN ] styles.write_xf34
|
||||
/// [ OK ] styles.write_xf34 (1 ms)
|
||||
/// [ RUN ] styles.write_xf35
|
||||
/// [ OK ] styles.write_xf35 (0 ms)
|
||||
/// [ RUN ] styles.write_xf36
|
||||
/// [ OK ] styles.write_xf36 (0 ms)
|
||||
/// [ RUN ] styles.xml_declaration
|
||||
/// [ OK ] styles.xml_declaration (0 ms)
|
||||
/// [----------] 74 tests from styles (17 ms total)
|
||||
///
|
||||
/// [----------] Global test environment tear-down
|
||||
/// [==========] 146 tests from 10 test cases ran. (33 ms total)
|
||||
/// [ PASSED ] 146 tests.
|
||||
///
|
||||
///
|
||||
///Both functional and unit test can be run together:
|
||||
///
|
||||
/// $ make test
|
||||
///
|
||||
///
|
||||
///## Valgrind Tests
|
||||
///
|
||||
///The functional tests and examples can be run under
|
||||
///[Valgrind](http://valgrind.org) to verify that there are no memory leaks.
|
||||
///
|
||||
///Install `valgrind` as follows:
|
||||
///
|
||||
/// apt-get install -y valgrind
|
||||
///
|
||||
///Then run the tests:
|
||||
///
|
||||
/// make test_valgrind
|
||||
///
|
||||
/// Next: @ref faq
|
112
docs/src/tutorial01.dox
Normal file
@ -0,0 +1,112 @@
|
||||
/**
|
||||
@page tutorial01 Tutorial 1: Create a simple XLSX file
|
||||
|
||||
|
||||
Let's start by creating a simple spreadsheet using C and the
|
||||
@c libxlsxwriter library.
|
||||
|
||||
Say that we have some data on monthly outgoings that we want to convert
|
||||
into an Excel XLSX file:
|
||||
|
||||
Item | Cost
|
||||
----- | ---:
|
||||
Rent | 1000
|
||||
Gas | 100
|
||||
Food | 300
|
||||
Gym | 50
|
||||
|
||||
To do that we can start with a small program like the following:
|
||||
|
||||
@dontinclude tutorial1.c
|
||||
@skip include
|
||||
@until };
|
||||
@until };
|
||||
@until }
|
||||
@until }
|
||||
|
||||
|
||||
If we run this program we should get a spreadsheet that looks like this:
|
||||
|
||||
@image html tutorial01.png
|
||||
|
||||
This is a simple example but the steps involved are representative of
|
||||
all programs that use @c libxlsxwriter, so let's break it down into separate
|
||||
parts.
|
||||
|
||||
The first step is to include the header for the library:
|
||||
|
||||
@dontinclude tutorial1.c
|
||||
@skipline include
|
||||
|
||||
Then we need some data to add to the spreadsheet. For the sake of this example
|
||||
we create and initialise some simple data structures. In a real application
|
||||
the input data might come from a database or a file.
|
||||
|
||||
@dontinclude tutorial1.c
|
||||
@skipline struct
|
||||
@until };
|
||||
@until };
|
||||
|
||||
|
||||
The next step is to create a workbook object in a @c main block or
|
||||
function using the new_workbook() function which takes the filename
|
||||
that we want to create:
|
||||
|
||||
@dontinclude tutorial1.c
|
||||
@skipline new_workbook
|
||||
|
||||
|
||||
The workbook object is then used to add a new worksheet via the
|
||||
workbook_add_worksheet() function:
|
||||
|
||||
@dontinclude tutorial1.c
|
||||
@skipline add_worksheet
|
||||
|
||||
If a `NULL` pointer is used for the worksheet name then a default name will be
|
||||
supplied using the Excel convention of `Sheet1`, `Sheet2`, etc. However we can
|
||||
also specify a name:
|
||||
|
||||
@code
|
||||
worksheet = workbook_add_worksheet(workbook, NULL ); // Defaults to Sheet1.
|
||||
worksheet = workbook_add_worksheet(workbook, "Data"); // Data.
|
||||
worksheet = workbook_add_worksheet(workbook, NULL ); // Defaults to Sheet3.
|
||||
@endcode
|
||||
|
||||
We can then use the worksheet object to write data via the
|
||||
worksheet_write_string() and worksheet_write_number() functions:
|
||||
|
||||
@code
|
||||
worksheet_write_string(worksheet, 0, 0, "Hello", NULL);
|
||||
worksheet_write_number(worksheet, 1, 0, 1234.56, NULL);
|
||||
@endcode
|
||||
|
||||
@note
|
||||
Rows and columns are zero indexed throughout the libxlsxwriter API. Thus, the
|
||||
first cell in a worksheet, `A1`, is equivalent to `(0, 0)`.
|
||||
|
||||
So in our example we iterate over our data and write it out as follows:
|
||||
|
||||
@dontinclude tutorial1.c
|
||||
@skipline for
|
||||
@until }
|
||||
|
||||
We then add a formula to calculate the total of the items in the second
|
||||
column:
|
||||
|
||||
@dontinclude tutorial1.c
|
||||
@skipline write_formula
|
||||
|
||||
Finally, we close the Excel file via the close method:
|
||||
|
||||
@dontinclude tutorial1.c
|
||||
@skipline close
|
||||
|
||||
And that's it. We now have a file that can be read by Excel and other
|
||||
spreadsheet applications.
|
||||
|
||||
In the next sections we will see how we can use the @c libxlsxwriter module
|
||||
to add formatting and other Excel features.
|
||||
|
||||
Next: @ref tutorial02.
|
||||
|
||||
*/
|
54
docs/src/tutorial02.dox
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
@page tutorial02 Tutorial 2: Adding formatting to the XLSX File
|
||||
|
||||
|
||||
In the previous section we created a simple spreadsheet using C and
|
||||
the @c libxlsxwriter library.
|
||||
|
||||
This converted the required data into an Excel file but it looked a
|
||||
little bare. In order to make the information clearer we would like to
|
||||
add some simple formatting, like this:
|
||||
|
||||
@image html tutorial02.png
|
||||
|
||||
The differences here are that we have added **Item** and **Cost** column
|
||||
headers in a bold font, we have formatted the currency in the second
|
||||
column and we have made the **Total** string bold.
|
||||
|
||||
To do this we can extend our program as follows:
|
||||
|
||||
@dontinclude tutorial2.c
|
||||
@skip include
|
||||
@until };
|
||||
@until };
|
||||
@until }
|
||||
@until }
|
||||
|
||||
The main difference between this and the previous program is that we have
|
||||
added two @ref format.h "Format" objects that we can use to format cells in
|
||||
the spreadsheet.
|
||||
|
||||
Format objects represent all of the formatting properties that can be applied
|
||||
to a cell in Excel such as fonts, number formatting, colors and borders. This
|
||||
is explained in more detail in @ref format.h "The Format object" and @ref
|
||||
working_with_formats.
|
||||
|
||||
For now we will avoid getting into the details and just use a limited
|
||||
amount of the format functionality to add some simple formatting:
|
||||
|
||||
@dontinclude tutorial2.c
|
||||
@skipline bold
|
||||
@until num_format
|
||||
|
||||
We can then pass these formats as a parameter to the `worksheet_write*()`
|
||||
functions to format the data in the cell:
|
||||
|
||||
@dontinclude tutorial2.c
|
||||
@skipline Total
|
||||
@skipline SUM
|
||||
|
||||
In the next section we will look at handling more data types.
|
||||
|
||||
Next: @ref tutorial03.
|
||||
|
||||
*/
|
90
docs/src/tutorial03.dox
Normal file
@ -0,0 +1,90 @@
|
||||
/**
|
||||
@page tutorial03 Tutorial 3: Writing different types of data to the XLSX File
|
||||
|
||||
|
||||
In the previous section we created a simple spreadsheet with formatting
|
||||
using C and the @c libxlsxwriter module.
|
||||
|
||||
This time let's extend the data we want to write to include some dates:
|
||||
|
||||
Item | Date | Cost
|
||||
---- | ---------- | ---:
|
||||
Rent | 2013-01-13 | 1000
|
||||
Gas | 2013-01-14 | 100
|
||||
Food | 2013-01-16 | 300
|
||||
Gym | 2013-01-20 | 50
|
||||
|
||||
|
||||
The corresponding spreadsheet will look like this:
|
||||
|
||||
@image html tutorial03.png
|
||||
|
||||
The differences here are that we have added a Date column with
|
||||
formatting and made that column a little wider to accommodate the dates.
|
||||
|
||||
To do this we can extend our program as follows:
|
||||
|
||||
@dontinclude tutorial3.c
|
||||
@skip include
|
||||
@until };
|
||||
@until };
|
||||
@until }
|
||||
@until }
|
||||
|
||||
The main difference between this and the previous program is that we have
|
||||
added a new @ref format.h "Format" object for dates and we have additional
|
||||
handling for the date information.
|
||||
|
||||
We have also extended the data that we are going to write to include a
|
||||
lxw_datetime struct to hold the date information. We will see how that is used
|
||||
shortly.
|
||||
|
||||
@dontinclude tutorial3.c
|
||||
@skipline struct
|
||||
@until };
|
||||
@until };
|
||||
|
||||
|
||||
|
||||
Excel treats different types of input data, such as strings and numbers,
|
||||
differently although it generally does it transparently to the user.
|
||||
Libxlsxwriter tries to emulate this in the `worksheet_write*()` functions by
|
||||
mapping C data types to types that Excel supports.
|
||||
|
||||
- worksheet_write_string()
|
||||
- worksheet_write_number()
|
||||
- worksheet_write_formula()
|
||||
- worksheet_write_datetime()
|
||||
- worksheet_write_blank()
|
||||
|
||||
In this version of our program we have used some of these functions for
|
||||
different types of data:
|
||||
|
||||
@dontinclude tutorial3.c
|
||||
@skipline expenses[i].item
|
||||
@until expenses[i].cost
|
||||
|
||||
The handling of dates is also new to our program.
|
||||
|
||||
Dates and times in Excel are floating point numbers that have a number format
|
||||
applied to display them in the correct format. Libxlsxwriter provides the
|
||||
worksheet_write_datetime() and the lxw_datetime struct help to convert dates
|
||||
and times into Excel date and time numbers.
|
||||
|
||||
The worksheet_write_datetime() function converts the lxw_datetime struct to a
|
||||
number that represents an Excel date but we also need to add the number format
|
||||
to ensure that Excel displays it as as date:
|
||||
|
||||
@dontinclude tutorial3.c
|
||||
@skipline yyyy
|
||||
|
||||
Date handling is explained in more detail in @ref working_with_dates.
|
||||
|
||||
That completes the tutorial section.
|
||||
|
||||
In the next sections we will look at the API in more detail starting
|
||||
with workbook.
|
||||
|
||||
Next: @ref workbook.h "The Workbook object"
|
||||
|
||||
*/
|
42
docs/src/working_with_colors.dox
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
@page working_with_colors Working with Colors
|
||||
|
||||
Throughout libxlsxwriter colors are specified using a Html style RGB
|
||||
integer value. For example with a Format object:
|
||||
|
||||
@code
|
||||
format_set_font_color(format, 0x3030E0);
|
||||
@endcode
|
||||
|
||||
For convenience a limited number of color names are supported:
|
||||
|
||||
@code
|
||||
format_set_font_color(format, LXW_COLOR_RED);
|
||||
@endcode
|
||||
|
||||
The color names and corresponding RRGGBB value are shown below:
|
||||
|
||||
|
||||
Color | Define | Value
|
||||
-------- | --------------------- | ---------
|
||||
Black | #LXW_COLOR_BLACK | `0x000000`
|
||||
Blue | #LXW_COLOR_BLUE | `0x0000FF`
|
||||
Brown | #LXW_COLOR_BROWN | `0x800000`
|
||||
Cyan | #LXW_COLOR_CYAN | `0x00FFFF`
|
||||
Gray | #LXW_COLOR_GRAY | `0x808080`
|
||||
Green | #LXW_COLOR_GREEN | `0x008000`
|
||||
Lime | #LXW_COLOR_LIME | `0x00FF00`
|
||||
Magenta | #LXW_COLOR_MAGENTA | `0xFF00FF`
|
||||
Navy | #LXW_COLOR_NAVY | `0x000080`
|
||||
Orange | #LXW_COLOR_ORANGE | `0xFF6600`
|
||||
Pink | #LXW_COLOR_PINK | `0xFF00FF`
|
||||
Purple | #LXW_COLOR_PURPLE | `0x800080`
|
||||
Red | #LXW_COLOR_RED | `0xFF0000`
|
||||
Silver | #LXW_COLOR_SILVER | `0xC0C0C0`
|
||||
White | #LXW_COLOR_WHITE | `0xFFFFFF`
|
||||
Yellow | #LXW_COLOR_YELLOW | `0xFFFF00`
|
||||
|
||||
|
||||
Next: @ref working_with_dates
|
||||
|
||||
*/
|
80
docs/src/working_with_dates.dox
Normal file
@ -0,0 +1,80 @@
|
||||
/**
|
||||
@page working_with_dates Working with Dates and Times
|
||||
|
||||
|
||||
Dates and times in Excel are represented by real numbers. For example a date
|
||||
that is displayed in Excel as "Jan 1 2013 12:00 PM" is stored as the number
|
||||
41275.5.
|
||||
|
||||
The integer part of the number stores the number of days since the epoch,
|
||||
which is generally 1900, and the fractional part stores the percentage of the
|
||||
day.
|
||||
|
||||
A date or time in Excel is just like any other number. To display the number
|
||||
as a date you must apply an Excel number format to it. Here is an example:
|
||||
|
||||
@dontinclude dates_and_times01.c
|
||||
@skip include
|
||||
@until return
|
||||
@until }
|
||||
|
||||
@image html date_example01.png
|
||||
|
||||
To make working with dates and times a little easier the `libxlsxwriter`
|
||||
library provides the lxw_datetime struct and the worksheet_write_datetime()
|
||||
function.
|
||||
|
||||
The members of the lxw_datetime struct and the range of their values are:
|
||||
|
||||
Member | Value
|
||||
-------- | -----------
|
||||
year | 1900 - 9999
|
||||
month | 1 - 12
|
||||
day | 1 - 31
|
||||
hour | 0 - 23
|
||||
min | 0 - 59
|
||||
sec | 0 - 59.999
|
||||
|
||||
Dates in Excel do not support timezones and the maximum resolution of times is
|
||||
milliseconds.
|
||||
|
||||
If dates or times are required without the other you should initialise the
|
||||
unrequired values to `0`:
|
||||
|
||||
@code
|
||||
// Date and time.
|
||||
lxw_datetime datetime1 = {2014, 11, 25, 17, 45, 5.1};
|
||||
|
||||
// Date only.
|
||||
lxw_datetime datetime2 = {2014, 11, 25, 0, 0, 0};
|
||||
|
||||
// Time only.
|
||||
lxw_datetime datetime3 = {0, 0, 0, 17, 45, 5.1};
|
||||
@endcode
|
||||
|
||||
Using lxw_datetime and worksheet_write_datetime() the previous example can
|
||||
then be re-written as follows:
|
||||
|
||||
@dontinclude dates_and_times02.c
|
||||
@skip include
|
||||
@until return
|
||||
@until }
|
||||
|
||||
The output from this program is the same as the previous example.
|
||||
|
||||
@image html date_example02.png
|
||||
|
||||
Dates can be formatted using any of the date formats supported by Excel. Here
|
||||
is a longer example that shows the same date in a several different formats:
|
||||
|
||||
@dontinclude dates_and_times03.c
|
||||
@skip include
|
||||
@until return
|
||||
@until }
|
||||
|
||||
@image html date_example03.png
|
||||
|
||||
|
||||
Next: @ref working_with_memory
|
||||
|
||||
*/
|
146
docs/src/working_with_formats.dox
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
@page working_with_formats Working with Formats
|
||||
|
||||
The main functions and properties used to add formatting to a cell are shown
|
||||
in @ref format.h "The Format object". This section provides some additional
|
||||
information about working with formats.
|
||||
|
||||
## Creating and using a Format object
|
||||
|
||||
Formats are created by calling the workbook_add_format() method and properties
|
||||
as set using the various functions shown below:
|
||||
|
||||
@code
|
||||
lxw_format *format = workbook_add_format(workbook);
|
||||
|
||||
format_set_bold(format);
|
||||
format_set_font_color(format, LXW_COLOR_RED);
|
||||
@endcode
|
||||
|
||||
|
||||
Once a Format object has been created and its properties have been
|
||||
set it can be passed as an argument to the `worksheet_write*()` methods as
|
||||
follows:
|
||||
|
||||
@code
|
||||
worksheet_write_string(worksheet, 0, 0, "Hello", format);
|
||||
worksheet_write_number(worksheet, 1, 0, 123.456, format);
|
||||
@endcode
|
||||
|
||||
Formats can also be passed to the worksheet `worksheet_set_row()` and
|
||||
`worksheet_set_column()` methods to define the default formatting properties
|
||||
for a row or column:
|
||||
|
||||
@code
|
||||
# Not implemented in version 0.0.1.
|
||||
worksheet_set_row(worksheet, 2, format)
|
||||
worksheet_set_column(worksheet, 0, 20, format)
|
||||
@endcode
|
||||
|
||||
|
||||
## Format methods and Format properties
|
||||
|
||||
The following table shows the Excel format categories and the equivalent
|
||||
`libxlsxwriter` Format function:
|
||||
|
||||
| Category | Description | Method Name |
|
||||
| :-------------- | :------------------- | :--------------------------- |
|
||||
| **Font** | Font type | format_set_font_name() |
|
||||
| | Font size | format_set_font_size() |
|
||||
| | Font color | format_set_font_color() |
|
||||
| | Bold | format_set_bold() |
|
||||
| | Italic | format_set_italic() |
|
||||
| | Underline | format_set_underline() |
|
||||
| | Strikeout | format_set_font_strikeout() |
|
||||
| | Super/Subscript | format_set_font_script() |
|
||||
| **Number** | Numeric format | format_set_num_format() |
|
||||
| **Protection** | Unlock cells | format_set_unlocked() |
|
||||
| | Hide formulas | format_set_hidden() |
|
||||
| **Alignment** | Horizontal align | format_set_align() |
|
||||
| | Vertical align | format_set_align() |
|
||||
| | Rotation | format_set_rotation() |
|
||||
| | Text wrap | format_set_text_wrap() |
|
||||
| | Indentation | format_set_indent() |
|
||||
| | Shrink to fit | format_set_shrink() |
|
||||
| **Pattern** | Cell pattern | format_set_pattern() |
|
||||
| | Background color | format_set_bg_color() |
|
||||
| | Foreground color | format_set_fg_color() |
|
||||
| **Border** | Cell border | format_set_border() |
|
||||
| | Bottom border | format_set_bottom() |
|
||||
| | Top border | format_set_top() |
|
||||
| | Left border | format_set_left() |
|
||||
| | Right border | format_set_right() |
|
||||
| | Border color | format_set_border_color() |
|
||||
| | Bottom color | format_set_bottom_color() |
|
||||
| | Top color | format_set_top_color() |
|
||||
| | Left color | format_set_left_color() |
|
||||
| | Right color | format_set_right_color() |
|
||||
|
||||
|
||||
## Format Colors
|
||||
|
||||
Format property colors are specified using a Html style RGB integer value or a
|
||||
limited number of defined colors:
|
||||
@code
|
||||
format_set_font_color(format1, 0x3030E0);
|
||||
format_set_font_color(format2, LXW_COLOR_RED);
|
||||
@endcode
|
||||
|
||||
See see @ref working_with_colors for more details.
|
||||
|
||||
|
||||
## Format Defaults
|
||||
|
||||
The default Excel 2007+ cell format is Calibri 11 with all other properties
|
||||
off.
|
||||
|
||||
In general a format function call without an argument will turn a property on,
|
||||
for example:
|
||||
|
||||
@code
|
||||
lxw_format *format = workbook_add_format(workbook);
|
||||
|
||||
format_set_bold(format);
|
||||
@endcode
|
||||
|
||||
## Modifying and Reusing Formats
|
||||
|
||||
Once a format has been created it can be used and reused in
|
||||
`worksheet_write*()` functions across any number of worksheets:
|
||||
|
||||
@code
|
||||
lxw_format *myformat1 = workbook_add_format(workbook);
|
||||
format_set_bold(myformat1);
|
||||
|
||||
worksheet_write_string(worksheet1, 1, 4, "Some text", myformat1);
|
||||
worksheet_write_string(worksheet2, 1, 4, "Some text", myformat1);
|
||||
@endcode
|
||||
|
||||
However, each unique cell format in an `libxlsxwriter` spreadsheet must have a
|
||||
corresponding Format object. It isn't possible to use a Format with a
|
||||
`worksheet_write*()` method and then redefine it for use at a later
|
||||
stage. This is because a Format is applied to a cell not in its current state
|
||||
but in its final state. Consider the following example:
|
||||
|
||||
@code
|
||||
lxw_format *format = workbook_add_format(workbook);
|
||||
format_set_bold(format);
|
||||
|
||||
worksheet_write_string(worksheet, 0, 0, "Hello", format);
|
||||
|
||||
format_set_italic(format);
|
||||
|
||||
worksheet_write_string(worksheet, 1, 0, "World", format);
|
||||
@endcode
|
||||
|
||||
|
||||
Cell `(0, 0)` is assigned a format which with the font set to bold. However, the
|
||||
italic property is subsequently and used in cell `(1, 0)`. This has the effect
|
||||
of adding italic to any previous uses of `format`. The result in this case is
|
||||
that "Hello" and "World" will both appear as bold and italic.
|
||||
|
||||
|
||||
Next: @ref working_with_colors
|
||||
|
||||
|
||||
*/
|
18
docs/src/working_with_memory.dox
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
@page working_with_memory Working with Memory and Performance
|
||||
|
||||
|
||||
By default `libxlsxwriter` holds all cell data in memory. This is to allow
|
||||
future features where formatting is applied separately from the data.
|
||||
|
||||
The effect of this is that for large files libxlsxwriter can consume a lot of
|
||||
memory.
|
||||
|
||||
This issue will be resolved in the next 1-2 releases to allow a small constant
|
||||
memory usage like in the Perl and Python modules that libxlsxwriter was ported
|
||||
from.
|
||||
|
||||
Next: @ref examples
|
||||
|
||||
|
||||
*/
|
44
examples/Makefile
Normal file
@ -0,0 +1,44 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Makefile for libxlsxwriter examples.
|
||||
#
|
||||
# Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
#
|
||||
|
||||
# Keep the output quiet by default.
|
||||
Q=@
|
||||
ifdef V
|
||||
Q=
|
||||
endif
|
||||
|
||||
# Directory variables.
|
||||
INC_DIR = ../include
|
||||
|
||||
# Flags passed to the C++ compiler.
|
||||
CFLAGS += -g -Wall -Wextra
|
||||
|
||||
# Source files to compile.
|
||||
SRCS = $(wildcard *.c)
|
||||
EXES = $(patsubst %.c,%,$(SRCS))
|
||||
|
||||
LIBXLSXWRITER = ../src/libxlsxwriter.a
|
||||
|
||||
LIBS = $(LIBXLSXWRITER) -lz
|
||||
|
||||
all : $(LIBXLSXWRITER) $(EXES)
|
||||
|
||||
$(LIBXLSXWRITER):
|
||||
$(Q)make -C ../third_party/minizip
|
||||
$(Q)make -C ../src
|
||||
|
||||
clean :
|
||||
$(Q)rm -f $(EXES)
|
||||
|
||||
# Executable targets.
|
||||
%: %.c $(LIBXLSXWRITER)
|
||||
$(Q)$(CC) -I$(INC_DIR) $(CFLAGS) $< -o $@ $(LIBS)
|
||||
|
||||
test_valgrind: all
|
||||
$(Q)for exe in $(EXES); do \
|
||||
valgrind -q --error-exitcode=1 --leak-check=full ./$$exe; \
|
||||
done
|
56
examples/anatomy.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Anatomy of a simple libxlsxwriter program.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
/* Create a new workbook. */
|
||||
lxw_workbook *workbook = new_workbook("anatomy.xlsx");
|
||||
|
||||
/* Add a worksheet with a user defined sheet name. */
|
||||
lxw_worksheet *worksheet1 = workbook_add_worksheet(workbook, "Demo");
|
||||
|
||||
/* Add a worksheet with Excel's default sheet name: Sheet2. */
|
||||
lxw_worksheet *worksheet2 = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Add some cell formats. */
|
||||
lxw_format *myformat1 = workbook_add_format(workbook);
|
||||
lxw_format *myformat2 = workbook_add_format(workbook);
|
||||
|
||||
/* Set the bold property for the first format. */
|
||||
format_set_bold(myformat1);
|
||||
|
||||
/* Set a number format for the second format. */
|
||||
format_set_num_format(myformat2, "$#,##0.00");
|
||||
|
||||
|
||||
/* Write some unformatted data. */
|
||||
worksheet_write_string(worksheet1, 0, 0, "Peach", NULL);
|
||||
worksheet_write_string(worksheet1, 1, 0, "Plum", NULL);
|
||||
|
||||
/* Write formatted data. */
|
||||
worksheet_write_string(worksheet1, 2, 0, "Pear", myformat1);
|
||||
|
||||
/* Formats can be reused. */
|
||||
worksheet_write_string(worksheet1, 3, 0, "Persimmon", myformat1);
|
||||
|
||||
|
||||
/* Write some numbers. */
|
||||
worksheet_write_number(worksheet1, 5, 0, 123, NULL);
|
||||
worksheet_write_number(worksheet1, 6, 0, 4567.555, myformat2);
|
||||
|
||||
|
||||
/* Write to the second worksheet. */
|
||||
worksheet_write_string(worksheet2, 0, 0, "Some text", myformat1);
|
||||
|
||||
|
||||
/* Close the workbook, save the file and free any memory. */
|
||||
workbook_close(workbook);
|
||||
|
||||
return 0;
|
||||
}
|
39
examples/dates_and_times01.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Example of writing a dates and time in Excel using a number with date
|
||||
* formatting. This demonstrates that dates and times in Excel are just
|
||||
* formatted real numbers.
|
||||
*
|
||||
* An easier approach using a lxw_datetime struct is shown in example
|
||||
* dates_and_times02.c.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
/* A number to display as a date. */
|
||||
double number = 41333.5;
|
||||
|
||||
/* Create a new workbook and add a worksheet. */
|
||||
lxw_workbook *workbook = new_workbook("date_and_times01.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Add a format with date formatting. */
|
||||
lxw_format *format = workbook_add_format(workbook);
|
||||
format_set_num_format(format, "mmm d yyyy hh:mm AM/PM");
|
||||
|
||||
|
||||
/* Write the number without formatting. */
|
||||
worksheet_write_number(worksheet, 0, 0, number, NULL ); // 41333.5
|
||||
|
||||
/* Write the number with formatting. Note: the worksheet_write_datetime()
|
||||
* function is preferable for writing dates and times. This is for
|
||||
* demonstration purposes only.
|
||||
*/
|
||||
worksheet_write_number(worksheet, 1, 0, number, format); // Feb 28 2013 12:00 PM
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
32
examples/dates_and_times02.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Example of writing dates and times in Excel using an lxw_datetime struct
|
||||
* and date formatting.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
/* A datetime to display. */
|
||||
lxw_datetime datetime = {2013, 2, 28, 12, 0, 0.0};
|
||||
|
||||
/* Create a new workbook and add a worksheet. */
|
||||
lxw_workbook *workbook = new_workbook("date_and_times02.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Add a format with date formatting. */
|
||||
lxw_format *format = workbook_add_format(workbook);
|
||||
format_set_num_format(format, "mmm d yyyy hh:mm AM/PM");
|
||||
|
||||
|
||||
/* Write the datetime without formatting. */
|
||||
worksheet_write_datetime(worksheet, 0, 0, &datetime, NULL ); // 41333.5
|
||||
|
||||
/* Write the datetime with formatting. */
|
||||
worksheet_write_datetime(worksheet, 1, 0, &datetime, format); // Feb 28 2013 12:00 PM
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
67
examples/dates_and_times03.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Example of writing dates and times in Excel using different date formats.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
/* A datetime to display. */
|
||||
lxw_datetime datetime = {2013, 1, 23, 12, 30, 5.123};
|
||||
uint32_t row = 0;
|
||||
uint16_t col = 0;
|
||||
int i;
|
||||
|
||||
/* Examples date and time formats. In the output file compare how changing
|
||||
* the format strings changes the appearance of the date.
|
||||
*/
|
||||
char *date_formats[] = {
|
||||
"dd/mm/yy",
|
||||
"mm/dd/yy",
|
||||
"dd m yy",
|
||||
"d mm yy",
|
||||
"d mmm yy",
|
||||
"d mmmm yy",
|
||||
"d mmmm yyy",
|
||||
"d mmmm yyyy",
|
||||
"dd/mm/yy hh:mm",
|
||||
"dd/mm/yy hh:mm:ss",
|
||||
"dd/mm/yy hh:mm:ss.000",
|
||||
"hh:mm",
|
||||
"hh:mm:ss",
|
||||
"hh:mm:ss.000",
|
||||
};
|
||||
|
||||
/* Create a new workbook and add a worksheet. */
|
||||
lxw_workbook *workbook = new_workbook("date_and_times03.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Add a bold format. */
|
||||
lxw_format *bold = workbook_add_format(workbook);
|
||||
format_set_bold(bold);
|
||||
|
||||
/* Write the column headers. */
|
||||
worksheet_write_string(worksheet, row, col, "Formatted date", bold);
|
||||
worksheet_write_string(worksheet, row, col + 1, "Format", bold);
|
||||
|
||||
/* Write the same date and time using each of the above formats. */
|
||||
for (i = 0; i < 14; i++) {
|
||||
row++;
|
||||
|
||||
/* Create a format for the date or time.*/
|
||||
lxw_format *format = workbook_add_format(workbook);
|
||||
format_set_num_format(format, date_formats[i]);
|
||||
format_set_align(format, LXW_ALIGN_LEFT);
|
||||
|
||||
/* Write the datetime with each format. */
|
||||
worksheet_write_datetime(worksheet, row, col, &datetime, format);
|
||||
|
||||
/* Also write the format string for comparison. */
|
||||
worksheet_write_string(worksheet, row, col + 1, date_formats[i], NULL);
|
||||
}
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
37
examples/demo.c
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* A simple example of some of the features of the libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
/* Create a new workbook. */
|
||||
lxw_workbook *workbook = new_workbook("hello_world.xlsx");
|
||||
|
||||
/* Add a worksheet. */
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Add a format. */
|
||||
lxw_format *format = workbook_add_format(workbook);
|
||||
|
||||
/* Set the bold property for the format */
|
||||
format_set_bold(format);
|
||||
|
||||
/* Write some simple text. */
|
||||
worksheet_write_string(worksheet, 0, 0, "Hello", NULL);
|
||||
|
||||
/* Text with formatting. */
|
||||
worksheet_write_string(worksheet, 1, 0, "World", format);
|
||||
|
||||
/* Writer some numbers. */
|
||||
worksheet_write_number(worksheet, 1, 0, 123, NULL);
|
||||
worksheet_write_number(worksheet, 1, 0, 123.456, NULL);
|
||||
|
||||
workbook_close(workbook);
|
||||
|
||||
return 0;
|
||||
}
|
43
examples/format_font.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Example of writing some data with font formatting to a simple Excel
|
||||
* file using libxlsxwriter.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
/* Create a new workbook. */
|
||||
lxw_workbook *workbook = new_workbook("format_font.xlsx");
|
||||
|
||||
/* Add a worksheet. */
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Add some formats. */
|
||||
lxw_format *format1 = workbook_add_format(workbook);
|
||||
lxw_format *format2 = workbook_add_format(workbook);
|
||||
lxw_format *format3 = workbook_add_format(workbook);
|
||||
|
||||
/* Set the bold property for format 1. */
|
||||
format_set_bold(format1);
|
||||
|
||||
/* Set the italic property for format 2. */
|
||||
format_set_italic(format2);
|
||||
|
||||
/* Set the bold and italic properties for format 3. */
|
||||
format_set_bold (format3);
|
||||
format_set_italic(format3);
|
||||
|
||||
/* Write some formatted strings. */
|
||||
worksheet_write_string(worksheet, 0, 0, "This is bold", format1);
|
||||
worksheet_write_string(worksheet, 1, 0, "This is italic", format2);
|
||||
worksheet_write_string(worksheet, 2, 0, "Bold and italic", format3);
|
||||
|
||||
/* Close the workbook, save the file and free any memory. */
|
||||
workbook_close(workbook);
|
||||
|
||||
return 0;
|
||||
}
|
65
examples/format_num_format.c
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Example of writing some data with numeric formatting to a simple Excel file
|
||||
* using libxlsxwriter.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
/* Create a new workbook and add a worksheet. */
|
||||
lxw_workbook *workbook = new_workbook("format_num_format.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Add some formats. */
|
||||
lxw_format *format01 = workbook_add_format(workbook);
|
||||
lxw_format *format02 = workbook_add_format(workbook);
|
||||
lxw_format *format03 = workbook_add_format(workbook);
|
||||
lxw_format *format04 = workbook_add_format(workbook);
|
||||
lxw_format *format05 = workbook_add_format(workbook);
|
||||
lxw_format *format06 = workbook_add_format(workbook);
|
||||
lxw_format *format07 = workbook_add_format(workbook);
|
||||
lxw_format *format08 = workbook_add_format(workbook);
|
||||
lxw_format *format09 = workbook_add_format(workbook);
|
||||
lxw_format *format10 = workbook_add_format(workbook);
|
||||
lxw_format *format11 = workbook_add_format(workbook);
|
||||
|
||||
/* Set some example number formats. */
|
||||
format_set_num_format(format01, "0.000");
|
||||
format_set_num_format(format02, "#,##0");
|
||||
format_set_num_format(format03, "#,##0.00");
|
||||
format_set_num_format(format04, "0.00");
|
||||
format_set_num_format(format05, "mm/dd/yy");
|
||||
format_set_num_format(format06, "mmm d yyyy");
|
||||
format_set_num_format(format07, "d mmmm yyyy");
|
||||
format_set_num_format(format08, "dd/mm/yyyy hh:mm AM/PM");
|
||||
format_set_num_format(format09, "0 \"dollar and\" .00 \"cents\"");
|
||||
|
||||
/* Write data using the formats. */
|
||||
worksheet_write_number(worksheet, 0, 0, 3.1415926, NULL); // 3.1415926
|
||||
worksheet_write_number(worksheet, 1, 0, 3.1415926, format01); // 3.142
|
||||
worksheet_write_number(worksheet, 2, 0, 1234.56, format02); // 1,235
|
||||
worksheet_write_number(worksheet, 3, 0, 1234.56, format03); // 1,234.56
|
||||
worksheet_write_number(worksheet, 4, 0, 49.99, format04); // 49.99
|
||||
worksheet_write_number(worksheet, 5, 0, 36892.521, format05); // 01/01/01
|
||||
worksheet_write_number(worksheet, 6, 0, 36892.521, format06); // Jan 1 2001
|
||||
worksheet_write_number(worksheet, 7, 0, 36892.521, format07); // 1 January 2001
|
||||
worksheet_write_number(worksheet, 8, 0, 36892.521, format08); // 01/01/2001 12:30 AM
|
||||
worksheet_write_number(worksheet, 9, 0, 1.87, format09); // 1 dollar and .87 cents
|
||||
|
||||
/* Show limited conditional number formats. */
|
||||
format_set_num_format(format10, "[Green]General;[Red]-General;General");
|
||||
worksheet_write_number(worksheet, 10, 0, 123, format10); // > 0 Green
|
||||
worksheet_write_number(worksheet, 11, 0, -45, format10); // < 0 Red
|
||||
worksheet_write_number(worksheet, 12, 0, 0, format10); // = 0 Default color
|
||||
|
||||
/* Format a Zip code. */
|
||||
format_set_num_format(format11, "00000");
|
||||
worksheet_write_number(worksheet, 13, 0, 1209, format11);
|
||||
|
||||
/* Close the workbook, save the file and free any memory. */
|
||||
return workbook_close(workbook);
|
||||
}
|
21
examples/hello.c
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Example of writing some data to a simple Excel file using libxlsxwriter.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = new_workbook("hello_world.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
worksheet_write_string(worksheet, 0, 0, "Hello", NULL);
|
||||
worksheet_write_number(worksheet, 1, 0, 123, NULL);
|
||||
|
||||
workbook_close(workbook);
|
||||
|
||||
return 0;
|
||||
}
|
50
examples/tutorial1.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* A simple program to write some data to an Excel file using the
|
||||
* libxlsxwriter library.
|
||||
*
|
||||
* This program is shown, with explanations, in Tutorial 1 of the
|
||||
* libxlsxwriter documentation.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
/* Some data we want to write to the worksheet. */
|
||||
struct expense {
|
||||
char item[32];
|
||||
int cost;
|
||||
};
|
||||
|
||||
struct expense expenses[] = {
|
||||
{"Rent", 1000},
|
||||
{"Gas", 100},
|
||||
{"Food", 300},
|
||||
{"Gym", 50},
|
||||
};
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
/* Create a workbook and add a worksheet. */
|
||||
lxw_workbook *workbook = new_workbook("tutorial01.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Start from the first cell. Rows and columns are zero indexed. */
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
|
||||
/* Iterate over the data and write it out element by element. */
|
||||
for (row = 0; row < 4; row++) {
|
||||
worksheet_write_string(worksheet, row, col, expenses[row].item, NULL);
|
||||
worksheet_write_number(worksheet, row, col + 1, expenses[row].cost, NULL);
|
||||
}
|
||||
|
||||
/* Write a total using a formula. */
|
||||
worksheet_write_string (worksheet, row, col, "Total", NULL);
|
||||
worksheet_write_formula(worksheet, row, col + 1, "=SUM(B1:B4)", NULL);
|
||||
|
||||
/* Save the workbook and free any allocated memory. */
|
||||
return workbook_close(workbook);
|
||||
}
|
63
examples/tutorial2.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* A simple program to write some data to an Excel file using the
|
||||
* libxlsxwriter library.
|
||||
*
|
||||
* This program is shown, with explanations, in Tutorial 2 of the
|
||||
* libxlsxwriter documentation.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
/* Some data we want to write to the worksheet. */
|
||||
struct expense {
|
||||
char item[32];
|
||||
int cost;
|
||||
};
|
||||
|
||||
struct expense expenses[] = {
|
||||
{"Rent", 1000},
|
||||
{"Gas", 100},
|
||||
{"Food", 300},
|
||||
{"Gym", 50},
|
||||
};
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
/* Create a workbook and add a worksheet. */
|
||||
lxw_workbook *workbook = new_workbook("tutorial02.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
int i;
|
||||
|
||||
/* Add a bold format to use to highlight cells. */
|
||||
lxw_format *bold = workbook_add_format(workbook);
|
||||
format_set_bold(bold);
|
||||
|
||||
/* Add a number format for cells with money. */
|
||||
lxw_format *money = workbook_add_format(workbook);
|
||||
format_set_num_format(money, "$#,##0");
|
||||
|
||||
/* Write some data header. */
|
||||
worksheet_write_string(worksheet, row, col, "Item", bold);
|
||||
worksheet_write_string(worksheet, row, col + 1, "Cost", bold);
|
||||
|
||||
/* Iterate over the data and write it out element by element. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
/* Write from the first cell below the headers. */
|
||||
row = i + 1;
|
||||
worksheet_write_string(worksheet, row, col, expenses[i].item, NULL);
|
||||
worksheet_write_number(worksheet, row, col + 1, expenses[i].cost, money);
|
||||
}
|
||||
|
||||
/* Write a total using a formula. */
|
||||
worksheet_write_string (worksheet, row + 1, col, "Total", bold);
|
||||
worksheet_write_formula(worksheet, row + 1, col + 1, "=SUM(B2:B5)", money);
|
||||
|
||||
/* Save the workbook and free any allocated memory. */
|
||||
return workbook_close(workbook);
|
||||
}
|
70
examples/tutorial3.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* A simple program to write some data to an Excel file using the
|
||||
* libxlsxwriter library.
|
||||
*
|
||||
* This program is shown, with explanations, in Tutorial 3 of the
|
||||
* libxlsxwriter documentation.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
/* Some data we want to write to the worksheet. */
|
||||
struct expense {
|
||||
char item[32];
|
||||
int cost;
|
||||
lxw_datetime datetime;
|
||||
};
|
||||
|
||||
struct expense expenses[] = {
|
||||
{"Rent", 1000, { .year = 2013, .month = 1, .day = 13 } },
|
||||
{"Gas", 100, { .year = 2013, .month = 1, .day = 14 } },
|
||||
{"Food", 300, { .year = 2013, .month = 1, .day = 16 } },
|
||||
{"Gym", 50, { .year = 2013, .month = 1, .day = 20 } },
|
||||
};
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
/* Create a workbook and add a worksheet. */
|
||||
lxw_workbook *workbook = new_workbook("tutorial03.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
int i;
|
||||
|
||||
/* Add a bold format to use to highlight cells. */
|
||||
lxw_format *bold = workbook_add_format(workbook);
|
||||
format_set_bold(bold);
|
||||
|
||||
/* Add a number format for cells with money. */
|
||||
lxw_format *money = workbook_add_format(workbook);
|
||||
format_set_num_format(money, "$#,##0");
|
||||
|
||||
/* Add an Excel date format. */
|
||||
lxw_format *date_format = workbook_add_format(workbook);
|
||||
format_set_num_format(date_format, "mmmm d yyyy");
|
||||
|
||||
|
||||
/* Write some data header. */
|
||||
worksheet_write_string(worksheet, row, col, "Item", bold);
|
||||
worksheet_write_string(worksheet, row, col + 1, "Cost", bold);
|
||||
|
||||
/* Iterate over the data and write it out elementt by element. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
/* Write from the first cell below the headers. */
|
||||
row = i + 1;
|
||||
worksheet_write_string (worksheet, row, col, expenses[i].item, NULL);
|
||||
worksheet_write_datetime(worksheet, row, col + 1, &expenses[i].datetime, date_format);
|
||||
worksheet_write_number (worksheet, row, col + 2, expenses[i].cost, money);
|
||||
}
|
||||
|
||||
/* Write a total using a formula. */
|
||||
worksheet_write_string (worksheet, row + 1, col, "Total", bold);
|
||||
worksheet_write_formula(worksheet, row + 1, col + 2, "=SUM(C2:C5)", money);
|
||||
|
||||
/* Save the workbook and free any allocated memory. */
|
||||
return workbook_close(workbook);
|
||||
}
|
20
examples/utf8.c
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* A simple Unicode UTF-8 example using libxlsxwriter.
|
||||
*
|
||||
* Note: The source file must be UTF-8 encoded.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = new_workbook("utf8.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
worksheet_write_string(worksheet, 2, 1, "Это фраза на русском!", NULL);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
25
include/xlsxwriter.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file xlsxwriter.h
|
||||
*
|
||||
* xlsxwriter - A library for creating Excel XLSX files.
|
||||
*
|
||||
* TODO.
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_XLSXWRITER_H__
|
||||
#define __LXW_XLSXWRITER_H__
|
||||
|
||||
#include "xlsxwriter/workbook.h"
|
||||
#include "xlsxwriter/worksheet.h"
|
||||
#include "xlsxwriter/format.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
|
||||
#define LXW_VERSION "0.0.1"
|
||||
|
||||
#endif /* __LXW_XLSXWRITER_H__ */
|
79
include/xlsxwriter/app.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
* app - A libxlsxwriter library for creating Excel XLSX app files.
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_APP_H__
|
||||
#define __LXW_APP_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* Define the queue.h TAILQ structs for the App structs. */
|
||||
STAILQ_HEAD(lxw_heading_pairs, lxw_heading_pair);
|
||||
STAILQ_HEAD(lxw_part_names, lxw_part_name);
|
||||
|
||||
typedef struct lxw_heading_pair {
|
||||
|
||||
char *key;
|
||||
char *value;
|
||||
|
||||
STAILQ_ENTRY (lxw_heading_pair) list_pointers;
|
||||
|
||||
} lxw_heading_pair;
|
||||
|
||||
typedef struct lxw_part_name {
|
||||
|
||||
char *name;
|
||||
|
||||
STAILQ_ENTRY (lxw_part_name) list_pointers;
|
||||
|
||||
} lxw_part_name;
|
||||
|
||||
/* Struct to represent an App object. */
|
||||
typedef struct lxw_app {
|
||||
|
||||
FILE *file;
|
||||
|
||||
struct lxw_heading_pairs *heading_pairs;
|
||||
struct lxw_part_names *part_names;
|
||||
lxw_doc_properties *properties;
|
||||
|
||||
size_t num_heading_pairs;
|
||||
size_t num_part_names;
|
||||
|
||||
} lxw_app;
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
lxw_app *_new_app();
|
||||
void _free_app(lxw_app *app);
|
||||
void _app_assemble_xml_file(lxw_app *self);
|
||||
void _add_part_name(lxw_app *self, const char *name);
|
||||
void _add_heading_pair(lxw_app *self, const char *key, const char *value);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
STATIC void _app_xml_declaration(lxw_app *self);
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_APP_H__ */
|
96
include/xlsxwriter/common.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
* common - Common functions and defines for the libxlsxwriter library.
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_COMMON_H__
|
||||
#define __LXW_COMMON_H__
|
||||
|
||||
#include <time.h>
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
|
||||
#ifndef TESTING
|
||||
/* Turn off until release. TODO */
|
||||
/* #define STATIC static */
|
||||
#define STATIC
|
||||
#else
|
||||
#define STATIC
|
||||
#endif
|
||||
|
||||
#define XL_SHEETNAME_MAX 32
|
||||
#define LXW_SHEETNAME_LEN 65
|
||||
|
||||
enum lxw_boolean {
|
||||
LXW_FALSE,
|
||||
LXW_TRUE
|
||||
};
|
||||
|
||||
#define ERROR(message) \
|
||||
fprintf(stderr, "[ERROR][%s:%d]: " message "\n", __FILE__, __LINE__)
|
||||
|
||||
#define MEM_ERROR() \
|
||||
ERROR("Memory allocation failed.")
|
||||
|
||||
#define GOTO_LABEL_ON_MEM_ERROR(pointer, label) \
|
||||
if (!pointer) { \
|
||||
MEM_ERROR(); \
|
||||
goto label; \
|
||||
}
|
||||
|
||||
#define RETURN_ON_MEM_ERROR(pointer, error) \
|
||||
if (!pointer) { \
|
||||
MEM_ERROR(); \
|
||||
return error; \
|
||||
}
|
||||
|
||||
#define LXW_WARN(message) \
|
||||
fprintf(stderr, "[WARN]: " message "\n")
|
||||
|
||||
/* Define the queue.h structs for the formats list. */
|
||||
STAILQ_HEAD(lxw_formats, lxw_format);
|
||||
|
||||
/* Define the queue.h structs for the generic data structs. */
|
||||
STAILQ_HEAD(lxw_tuples, lxw_tuple);
|
||||
|
||||
typedef struct lxw_tuple {
|
||||
char *key;
|
||||
char *value;
|
||||
|
||||
STAILQ_ENTRY (lxw_tuple) list_pointers;
|
||||
} lxw_tuple;
|
||||
|
||||
typedef struct lxw_doc_properties {
|
||||
char *title;
|
||||
char *subject;
|
||||
char *author;
|
||||
char *manager;
|
||||
char *company;
|
||||
char *category;
|
||||
char *keywords;
|
||||
char *comments;
|
||||
char *status;
|
||||
time_t created;
|
||||
} lxw_doc_properties;
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_COMMON_H__ */
|
70
include/xlsxwriter/content_types.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
* content_types - A libxlsxwriter library for creating Excel XLSX
|
||||
* content_types files.
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_CONTENT_TYPES_H__
|
||||
#define __LXW_CONTENT_TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define LXW_CONTENT_TYPE_SCHEMA "http://schemas.openxmlformats.org/package/2006/content-types"
|
||||
#define LXW_APP_PACKAGE "application/vnd.openxmlformats-package."
|
||||
#define LXW_APP_DOCUMENT "application/vnd.openxmlformats-officedocument."
|
||||
|
||||
/*
|
||||
* Struct to represent a content_types.
|
||||
*/
|
||||
typedef struct lxw_content_types {
|
||||
|
||||
FILE *file;
|
||||
|
||||
struct lxw_tuples *default_types;
|
||||
struct lxw_tuples *overrides;
|
||||
|
||||
} lxw_content_types;
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
lxw_content_types *_new_content_types();
|
||||
void _free_content_types(lxw_content_types *content_types);
|
||||
void _content_types_assemble_xml_file(lxw_content_types *self);
|
||||
void _ct_add_default(lxw_content_types *self, const char *key,
|
||||
const char *value);
|
||||
void _ct_add_override(lxw_content_types *self, const char *key,
|
||||
const char *value);
|
||||
void _ct_add_worksheet_name(lxw_content_types *self, const char *str);
|
||||
void _ct_add_shared_strings(lxw_content_types *self);
|
||||
void _ct_add_calc_chain(lxw_content_types *self);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
STATIC void _content_types_xml_declaration(lxw_content_types *self);
|
||||
STATIC void _write_default(lxw_content_types *self, const char *ext,
|
||||
const char *type);
|
||||
STATIC void _write_override(lxw_content_types *self, const char *part_name,
|
||||
const char *type);
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_CONTENT_TYPES_H__ */
|
51
include/xlsxwriter/core.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
* core - A libxlsxwriter library for creating Excel XLSX core files.
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_CORE_H__
|
||||
#define __LXW_CORE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Struct to represent a core.
|
||||
*/
|
||||
typedef struct lxw_core {
|
||||
|
||||
FILE *file;
|
||||
lxw_doc_properties *properties;
|
||||
|
||||
} lxw_core;
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
lxw_core *_new_core();
|
||||
void _free_core(lxw_core *core);
|
||||
void _core_assemble_xml_file(lxw_core *self);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
STATIC void _core_xml_declaration(lxw_core *self);
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_CORE_H__ */
|
1190
include/xlsxwriter/format.h
Normal file
73
include/xlsxwriter/hash_table.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
* hash_table - Hash table functions for libxlsxwriter.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LXW_HASH_TABLE_H__
|
||||
#define __LXW_HASH_TABLE_H__
|
||||
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
#include "common.h"
|
||||
|
||||
/* List declarations. */
|
||||
STAILQ_HEAD(lxw_hash_order_list, lxw_hash_element);
|
||||
SLIST_HEAD(lxw_hash_bucket_list, lxw_hash_element);
|
||||
|
||||
/* LXW_HASH hash table struct. */
|
||||
typedef struct lxw_hash_table {
|
||||
size_t num_buckets;
|
||||
size_t used_buckets;
|
||||
size_t unique_count;
|
||||
uint8_t free_key;
|
||||
uint8_t free_value;
|
||||
|
||||
struct lxw_hash_order_list *order_list;
|
||||
struct lxw_hash_bucket_list **buckets;
|
||||
} lxw_hash_table;
|
||||
|
||||
/*
|
||||
* LXW_HASH table element struct.
|
||||
*
|
||||
* The hash elements contain pointers to allow them to be stored in
|
||||
* lists in the the hash table buckets and also pointers to track the
|
||||
* insertion order in a separate list.
|
||||
*/
|
||||
typedef struct lxw_hash_element {
|
||||
void *key;
|
||||
void *value;
|
||||
|
||||
STAILQ_ENTRY (lxw_hash_element) lxw_hash_order_pointers;
|
||||
SLIST_ENTRY (lxw_hash_element) lxw_hash_list_pointers;
|
||||
} lxw_hash_element;
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
lxw_hash_element *_hash_key_exists(lxw_hash_table *lxw_hash, void *key,
|
||||
size_t key_len);
|
||||
lxw_hash_element *_insert_hash_element(lxw_hash_table *lxw_hash, void *key,
|
||||
void *value, size_t key_len);
|
||||
lxw_hash_table *_new_lxw_hash(size_t num_buckets, uint8_t free_key,
|
||||
uint8_t free_value);
|
||||
void _free_lxw_hash(lxw_hash_table *lxw_hash);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_HASH_TABLE_H__ */
|
69
include/xlsxwriter/packager.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
* packager - A libxlsxwriter library for creating Excel XLSX packager files.
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_PACKAGER_H__
|
||||
#define __LXW_PACKAGER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
#include "xlsxwriter/third_party/minizip/zip.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "workbook.h"
|
||||
#include "worksheet.h"
|
||||
#include "shared_strings.h"
|
||||
#include "app.h"
|
||||
#include "core.h"
|
||||
#include "theme.h"
|
||||
#include "styles.h"
|
||||
#include "format.h"
|
||||
#include "content_types.h"
|
||||
#include "relationships.h"
|
||||
|
||||
#define FILENAME_LEN 128
|
||||
#define LXW_ZIP_BUFFER_SIZE (16384)
|
||||
|
||||
/*
|
||||
* Struct to represent a packager.
|
||||
*/
|
||||
typedef struct lxw_packager {
|
||||
|
||||
FILE *file;
|
||||
lxw_workbook *workbook;
|
||||
|
||||
size_t buffer_size;
|
||||
zipFile zipfile;
|
||||
zip_fileinfo zipfile_info;
|
||||
char *filename;
|
||||
char *buffer;
|
||||
|
||||
} lxw_packager;
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
lxw_packager *_new_packager(const char *filename);
|
||||
void _free_packager(lxw_packager *packager);
|
||||
uint8_t _create_package(lxw_packager *self);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_PACKAGER_H__ */
|
82
include/xlsxwriter/relationships.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
* relationships - A libxlsxwriter library for creating Excel XLSX
|
||||
* relationships files.
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_RELATIONSHIPS_H__
|
||||
#define __LXW_RELATIONSHIPS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define LXW_SCHEMA_ROOT "http://schemas.openxmlformats.org"
|
||||
#define LXW_PACKAGE_SCHEMA LXW_SCHEMA_ROOT "/package/2006/relationships"
|
||||
#define LXW_DOCUMENT_SCHEMA LXW_SCHEMA_ROOT "/officeDocument/2006/relationships"
|
||||
#define LXW_MS_SCHEMA "http://schemas.microsoft.com/office/2006/relationships"
|
||||
|
||||
/* Define the queue.h STAILQ structs for the generic data structs. */
|
||||
STAILQ_HEAD(lxw_rel_tuples, lxw_rel_tuple);
|
||||
|
||||
typedef struct lxw_rel_tuple {
|
||||
|
||||
char *type;
|
||||
char *target;
|
||||
char *target_mode;
|
||||
|
||||
STAILQ_ENTRY (lxw_rel_tuple) list_pointers;
|
||||
|
||||
} lxw_rel_tuple;
|
||||
|
||||
/*
|
||||
* Struct to represent a relationships.
|
||||
*/
|
||||
typedef struct lxw_relationships {
|
||||
|
||||
FILE *file;
|
||||
|
||||
uint32_t rel_id;
|
||||
struct lxw_rel_tuples *relationships;
|
||||
|
||||
} lxw_relationships;
|
||||
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
lxw_relationships *_new_relationships();
|
||||
void _free_relationships(lxw_relationships *relationships);
|
||||
void _relationships_assemble_xml_file(lxw_relationships *self);
|
||||
|
||||
void _add_document_relationship(lxw_relationships *self, const char *type,
|
||||
const char *target);
|
||||
void _add_package_relationship(lxw_relationships *self, const char *type,
|
||||
const char *target);
|
||||
void _add_ms_package_relationship(lxw_relationships *self, const char *type,
|
||||
const char *target);
|
||||
void _add_worksheet_relationship(lxw_relationships *self, const char *type,
|
||||
const char *target, const char *target_mode);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
STATIC void _relationships_xml_declaration(lxw_relationships *self);
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_RELATIONSHIPS_H__ */
|
84
include/xlsxwriter/shared_strings.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
* shared_strings - A libxlsxwriter library for creating Excel XLSX
|
||||
* sst files.
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_SST_H__
|
||||
#define __LXW_SST_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define NUM_SST_BUCKETS 8
|
||||
/* STAILQ_HEAD() declaration. */
|
||||
struct sst_order_list {
|
||||
struct sst_element *stqh_first;
|
||||
struct sst_element **stqh_last;
|
||||
};
|
||||
|
||||
/* SLIST_HEAD() declaration. */
|
||||
struct sst_bucket_list {
|
||||
struct sst_element *slh_first;
|
||||
};
|
||||
|
||||
/*
|
||||
* Elements of the SST table. They contain pointers to allow them to
|
||||
* be stored in lists in the the hash table buckets and also pointers to
|
||||
* track the insertion order in a separate list.
|
||||
*/
|
||||
struct sst_element {
|
||||
size_t index;
|
||||
char *string;
|
||||
|
||||
STAILQ_ENTRY (sst_element) sst_order_pointers;
|
||||
SLIST_ENTRY (sst_element) sst_list_pointers;
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct to represent a sst.
|
||||
*/
|
||||
typedef struct lxw_sst {
|
||||
FILE *file;
|
||||
|
||||
size_t num_buckets;
|
||||
size_t used_buckets;
|
||||
size_t string_count;
|
||||
size_t unique_count;
|
||||
|
||||
struct sst_order_list *order_list;
|
||||
struct sst_bucket_list **buckets;
|
||||
|
||||
} lxw_sst;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
lxw_sst *_new_sst();
|
||||
void _free_sst(lxw_sst *sst);
|
||||
int32_t _get_sst_index(lxw_sst *sst, const char *string);
|
||||
void _sst_assemble_xml_file(lxw_sst *self);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
STATIC void _sst_xml_declaration(lxw_sst *self);
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_SST_H__ */
|
78
include/xlsxwriter/styles.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
* styles - A libxlsxwriter library for creating Excel XLSX styles files.
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_STYLES_H__
|
||||
#define __LXW_STYLES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
|
||||
#include "format.h"
|
||||
|
||||
/*
|
||||
* Struct to represent a styles.
|
||||
*/
|
||||
typedef struct lxw_styles {
|
||||
|
||||
FILE *file;
|
||||
uint32_t font_count;
|
||||
uint32_t xf_count;
|
||||
uint32_t dxf_count;
|
||||
uint32_t num_format_count;
|
||||
uint32_t border_count;
|
||||
uint32_t fill_count;
|
||||
struct lxw_formats *xf_formats;
|
||||
struct lxw_formats *dxf_formats;
|
||||
|
||||
} lxw_styles;
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
lxw_styles *_new_styles();
|
||||
void _free_styles(lxw_styles *styles);
|
||||
void _styles_assemble_xml_file(lxw_styles *self);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
STATIC void _styles_xml_declaration(lxw_styles *self);
|
||||
STATIC void _write_style_sheet(lxw_styles *self);
|
||||
STATIC void _write_font_size(lxw_styles *self, uint16_t font_size);
|
||||
STATIC void _write_font_color_theme(lxw_styles *self, uint8_t theme);
|
||||
STATIC void _write_font_name(lxw_styles *self, const char *font_name);
|
||||
STATIC void _write_font_family(lxw_styles *self, uint8_t font_family);
|
||||
STATIC void _write_font_scheme(lxw_styles *self, const char *font_scheme);
|
||||
STATIC void _write_font(lxw_styles *self, lxw_format *format);
|
||||
STATIC void _write_fonts(lxw_styles *self);
|
||||
STATIC void _write_default_fill(lxw_styles *self, const char *pattern);
|
||||
STATIC void _write_fills(lxw_styles *self);
|
||||
STATIC void _write_border(lxw_styles *self, lxw_format *format);
|
||||
STATIC void _write_borders(lxw_styles *self);
|
||||
STATIC void _write_style_xf(lxw_styles *self);
|
||||
STATIC void _write_cell_style_xfs(lxw_styles *self);
|
||||
STATIC void _write_xf(lxw_styles *self, lxw_format *format);
|
||||
STATIC void _write_cell_xfs(lxw_styles *self);
|
||||
STATIC void _write_cell_style(lxw_styles *self);
|
||||
STATIC void _write_cell_styles(lxw_styles *self);
|
||||
STATIC void _write_dxfs(lxw_styles *self);
|
||||
STATIC void _write_table_styles(lxw_styles *self);
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_STYLES_H__ */
|
50
include/xlsxwriter/theme.h
Normal file
208
include/xlsxwriter/third_party/minizip/ioapi.h
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
/* ioapi.h -- IO base function header for compress/uncompress .zip
|
||||
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
|
||||
|
||||
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
|
||||
|
||||
Modifications for Zip64 support
|
||||
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
|
||||
|
||||
For more info read MiniZip_info.txt
|
||||
|
||||
Changes
|
||||
|
||||
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)
|
||||
Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
|
||||
More if/def section may be needed to support other platforms
|
||||
Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
|
||||
(but you should use iowin32.c for windows instead)
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _ZLIBIOAPI64_H
|
||||
#define _ZLIBIOAPI64_H
|
||||
|
||||
#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
|
||||
|
||||
// Linux needs this to support file operation on files larger then 4+GB
|
||||
// But might need better if/def to select just the platforms that needs them.
|
||||
|
||||
#ifndef __USE_FILE_OFFSET64
|
||||
#define __USE_FILE_OFFSET64
|
||||
#endif
|
||||
#ifndef __USE_LARGEFILE64
|
||||
#define __USE_LARGEFILE64
|
||||
#endif
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
#ifndef _FILE_OFFSET_BIT
|
||||
#define _FILE_OFFSET_BIT 64
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "zlib.h"
|
||||
|
||||
#if defined(USE_FILE32API)
|
||||
#define fopen64 fopen
|
||||
#define ftello64 ftell
|
||||
#define fseeko64 fseek
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
#define fopen64 fopen
|
||||
#define ftello64 ftello
|
||||
#define fseeko64 fseeko
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#define fopen64 fopen
|
||||
#if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
|
||||
#define ftello64 _ftelli64
|
||||
#define fseeko64 _fseeki64
|
||||
#else // old MSC
|
||||
#define ftello64 ftell
|
||||
#define fseeko64 fseek
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
#ifndef ZPOS64_T
|
||||
#ifdef _WIN32
|
||||
#define ZPOS64_T fpos_t
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#define ZPOS64_T uint64_t
|
||||
#endif
|
||||
#endif
|
||||
*/
|
||||
|
||||
#ifdef HAVE_MINIZIP64_CONF_H
|
||||
#include "mz64conf.h"
|
||||
#endif
|
||||
|
||||
/* a type choosen by DEFINE */
|
||||
#ifdef HAVE_64BIT_INT_CUSTOM
|
||||
typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
|
||||
#else
|
||||
#ifdef HAS_STDINT_H
|
||||
#include "stdint.h"
|
||||
typedef uint64_t ZPOS64_T;
|
||||
#else
|
||||
|
||||
/* Maximum unsigned 32-bit value used as placeholder for zip64 */
|
||||
#define MAXU32 0xffffffff
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef unsigned __int64 ZPOS64_T;
|
||||
#else
|
||||
typedef unsigned long long int ZPOS64_T;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define ZLIB_FILEFUNC_SEEK_CUR (1)
|
||||
#define ZLIB_FILEFUNC_SEEK_END (2)
|
||||
#define ZLIB_FILEFUNC_SEEK_SET (0)
|
||||
|
||||
#define ZLIB_FILEFUNC_MODE_READ (1)
|
||||
#define ZLIB_FILEFUNC_MODE_WRITE (2)
|
||||
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
|
||||
|
||||
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
|
||||
#define ZLIB_FILEFUNC_MODE_CREATE (8)
|
||||
|
||||
|
||||
#ifndef ZCALLBACK
|
||||
#if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
|
||||
#define ZCALLBACK CALLBACK
|
||||
#else
|
||||
#define ZCALLBACK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
|
||||
typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
|
||||
typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
|
||||
typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
|
||||
typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
|
||||
|
||||
typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
|
||||
typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
|
||||
|
||||
|
||||
/* here is the "old" 32 bits structure structure */
|
||||
typedef struct zlib_filefunc_def_s
|
||||
{
|
||||
open_file_func zopen_file;
|
||||
read_file_func zread_file;
|
||||
write_file_func zwrite_file;
|
||||
tell_file_func ztell_file;
|
||||
seek_file_func zseek_file;
|
||||
close_file_func zclose_file;
|
||||
testerror_file_func zerror_file;
|
||||
voidpf opaque;
|
||||
} zlib_filefunc_def;
|
||||
|
||||
typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream));
|
||||
typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
|
||||
typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode));
|
||||
|
||||
typedef struct zlib_filefunc64_def_s
|
||||
{
|
||||
open64_file_func zopen64_file;
|
||||
read_file_func zread_file;
|
||||
write_file_func zwrite_file;
|
||||
tell64_file_func ztell64_file;
|
||||
seek64_file_func zseek64_file;
|
||||
close_file_func zclose_file;
|
||||
testerror_file_func zerror_file;
|
||||
voidpf opaque;
|
||||
} zlib_filefunc64_def;
|
||||
|
||||
void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
|
||||
void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
|
||||
|
||||
/* now internal definition, only for zip.c and unzip.h */
|
||||
typedef struct zlib_filefunc64_32_def_s
|
||||
{
|
||||
zlib_filefunc64_def zfile_func64;
|
||||
open_file_func zopen32_file;
|
||||
tell_file_func ztell32_file;
|
||||
seek_file_func zseek32_file;
|
||||
} zlib_filefunc64_32_def;
|
||||
|
||||
|
||||
#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
|
||||
#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
|
||||
/* #define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) */
|
||||
/* #define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) */
|
||||
#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
|
||||
#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
|
||||
|
||||
voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
|
||||
long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
|
||||
ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
|
||||
|
||||
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
|
||||
|
||||
#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
|
||||
#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
|
||||
#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
365
include/xlsxwriter/third_party/minizip/zip.h
vendored
Normal file
@ -0,0 +1,365 @@
|
||||
/* zip.h -- IO on .zip files using zlib
|
||||
Version 1.1, February 14h, 2010
|
||||
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
|
||||
|
||||
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
|
||||
|
||||
Modifications for Zip64 support
|
||||
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
|
||||
|
||||
For more info read MiniZip_info.txt
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Condition of use and distribution are the same than zlib :
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Changes
|
||||
|
||||
See header of zip.h
|
||||
|
||||
*/
|
||||
|
||||
/* Pragma added by libxlsxwriter project to avoid warnings with -pedantic -ansi. */
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _zip12_H
|
||||
#define _zip12_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* #define HAVE_BZIP2 */
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIBIOAPI_H
|
||||
#include "ioapi.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BZIP2
|
||||
#include "bzlib.h"
|
||||
#endif
|
||||
|
||||
#define Z_BZIP2ED 12
|
||||
|
||||
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagzipFile__ { int unused; } zipFile__;
|
||||
typedef zipFile__ *zipFile;
|
||||
#else
|
||||
typedef voidp zipFile;
|
||||
#endif
|
||||
|
||||
#define ZIP_OK (0)
|
||||
#define ZIP_EOF (0)
|
||||
#define ZIP_ERRNO (Z_ERRNO)
|
||||
#define ZIP_PARAMERROR (-102)
|
||||
#define ZIP_BADZIPFILE (-103)
|
||||
#define ZIP_INTERNALERROR (-104)
|
||||
|
||||
#ifndef DEF_MEM_LEVEL
|
||||
# if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
# else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
# endif
|
||||
#endif
|
||||
/* default memLevel */
|
||||
|
||||
/* tm_zip contain date/time info */
|
||||
typedef struct tm_zip_s
|
||||
{
|
||||
uInt tm_sec; /* seconds after the minute - [0,59] */
|
||||
uInt tm_min; /* minutes after the hour - [0,59] */
|
||||
uInt tm_hour; /* hours since midnight - [0,23] */
|
||||
uInt tm_mday; /* day of the month - [1,31] */
|
||||
uInt tm_mon; /* months since January - [0,11] */
|
||||
uInt tm_year; /* years - [1980..2044] */
|
||||
} tm_zip;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
tm_zip tmz_date; /* date in understandable format */
|
||||
uLong dosDate; /* if dos_date == 0, tmu_date is used */
|
||||
/* uLong flag; */ /* general purpose bit flag 2 bytes */
|
||||
|
||||
uLong internal_fa; /* internal file attributes 2 bytes */
|
||||
uLong external_fa; /* external file attributes 4 bytes */
|
||||
} zip_fileinfo;
|
||||
|
||||
typedef const char* zipcharpc;
|
||||
|
||||
|
||||
#define APPEND_STATUS_CREATE (0)
|
||||
#define APPEND_STATUS_CREATEAFTER (1)
|
||||
#define APPEND_STATUS_ADDINZIP (2)
|
||||
|
||||
extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
|
||||
extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append));
|
||||
/*
|
||||
Create a zipfile.
|
||||
pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
|
||||
an Unix computer "zlib/zlib113.zip".
|
||||
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
|
||||
will be created at the end of the file.
|
||||
(useful if the file contain a self extractor code)
|
||||
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
|
||||
add files in existing zip (be sure you don't add file that doesn't exist)
|
||||
If the zipfile cannot be opened, the return value is NULL.
|
||||
Else, the return value is a zipFile Handle, usable with other function
|
||||
of this zip package.
|
||||
*/
|
||||
|
||||
/* Note : there is no delete function into a zipfile.
|
||||
If you want delete file into a zipfile, you must open a zipfile, and create another
|
||||
Of couse, you can use RAW reading and writing to copy the file you did not want delte
|
||||
*/
|
||||
|
||||
extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
|
||||
int append,
|
||||
zipcharpc* globalcomment,
|
||||
zlib_filefunc_def* pzlib_filefunc_def));
|
||||
|
||||
extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname,
|
||||
int append,
|
||||
zipcharpc* globalcomment,
|
||||
zlib_filefunc64_def* pzlib_filefunc_def));
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level));
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int zip64));
|
||||
|
||||
/*
|
||||
Open a file in the ZIP for writing.
|
||||
filename : the filename in zip (if NULL, '-' without quote will be used
|
||||
*zipfi contain supplemental information
|
||||
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
|
||||
contains the extrafield data the the local header
|
||||
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
|
||||
contains the extrafield data the the local header
|
||||
if comment != NULL, comment contain the comment string
|
||||
method contain the compression method (0 for store, Z_DEFLATED for deflate)
|
||||
level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
|
||||
zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
|
||||
this MUST be '1' if the uncompressed size is >= 0xffffffff.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int raw));
|
||||
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int raw,
|
||||
int zip64));
|
||||
/*
|
||||
Same than zipOpenNewFileInZip, except if raw=1, we write raw file
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int raw,
|
||||
int windowBits,
|
||||
int memLevel,
|
||||
int strategy,
|
||||
const char* password,
|
||||
uLong crcForCrypting));
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int raw,
|
||||
int windowBits,
|
||||
int memLevel,
|
||||
int strategy,
|
||||
const char* password,
|
||||
uLong crcForCrypting,
|
||||
int zip64
|
||||
));
|
||||
|
||||
/*
|
||||
Same than zipOpenNewFileInZip2, except
|
||||
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
|
||||
password : crypting password (NULL for no crypting)
|
||||
crcForCrypting : crc of file to compress (needed for crypting)
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int raw,
|
||||
int windowBits,
|
||||
int memLevel,
|
||||
int strategy,
|
||||
const char* password,
|
||||
uLong crcForCrypting,
|
||||
uLong versionMadeBy,
|
||||
uLong flagBase
|
||||
));
|
||||
|
||||
|
||||
extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file,
|
||||
const char* filename,
|
||||
const zip_fileinfo* zipfi,
|
||||
const void* extrafield_local,
|
||||
uInt size_extrafield_local,
|
||||
const void* extrafield_global,
|
||||
uInt size_extrafield_global,
|
||||
const char* comment,
|
||||
int method,
|
||||
int level,
|
||||
int raw,
|
||||
int windowBits,
|
||||
int memLevel,
|
||||
int strategy,
|
||||
const char* password,
|
||||
uLong crcForCrypting,
|
||||
uLong versionMadeBy,
|
||||
uLong flagBase,
|
||||
int zip64
|
||||
));
|
||||
/*
|
||||
Same than zipOpenNewFileInZip4, except
|
||||
versionMadeBy : value for Version made by field
|
||||
flag : value for flag field (compression level info will be added)
|
||||
*/
|
||||
|
||||
|
||||
extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
|
||||
const void* buf,
|
||||
unsigned len));
|
||||
/*
|
||||
Write data in the zipfile
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
|
||||
/*
|
||||
Close the current file in the zipfile
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
|
||||
uLong uncompressed_size,
|
||||
uLong crc32));
|
||||
|
||||
extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file,
|
||||
ZPOS64_T uncompressed_size,
|
||||
uLong crc32));
|
||||
|
||||
/*
|
||||
Close the current file in the zipfile, for file opened with
|
||||
parameter raw=1 in zipOpenNewFileInZip2
|
||||
uncompressed_size and crc32 are value for the uncompressed size
|
||||
*/
|
||||
|
||||
extern int ZEXPORT zipClose OF((zipFile file,
|
||||
const char* global_comment));
|
||||
/*
|
||||
Close the zipfile
|
||||
*/
|
||||
|
||||
|
||||
extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader));
|
||||
/*
|
||||
zipRemoveExtraInfoBlock - Added by Mathias Svensson
|
||||
|
||||
Remove extra information block from a extra information data for the local file header or central directory header
|
||||
|
||||
It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode.
|
||||
|
||||
0x0001 is the signature header for the ZIP64 extra information blocks
|
||||
|
||||
usage.
|
||||
Remove ZIP64 Extra information from a central director extra field data
|
||||
zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001);
|
||||
|
||||
Remove ZIP64 Extra information from a Local File Header extra field data
|
||||
zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001);
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _zip64_H */
|
694
include/xlsxwriter/third_party/queue.h
vendored
Normal file
@ -0,0 +1,694 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* This file defines four types of data structures: singly-linked lists,
|
||||
* singly-linked tail queues, lists and tail queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The elements
|
||||
* are singly linked for minimum space and pointer manipulation overhead at
|
||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||
* added to the list after an existing element or at the head of the list.
|
||||
* Elements being removed from the head of the list should use the explicit
|
||||
* macro for this purpose for optimum efficiency. A singly-linked list may
|
||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||
* for applications with large datasets and few or no removals or for
|
||||
* implementing a LIFO queue.
|
||||
*
|
||||
* A singly-linked tail queue is headed by a pair of pointers, one to the
|
||||
* head of the list and the other to the tail of the list. The elements are
|
||||
* singly linked for minimum space and pointer manipulation overhead at the
|
||||
* expense of O(n) removal for arbitrary elements. New elements can be added
|
||||
* to the list after an existing element, at the head of the list, or at the
|
||||
* end of the list. Elements being removed from the head of the tail queue
|
||||
* should use the explicit macro for this purpose for optimum efficiency.
|
||||
* A singly-linked tail queue may only be traversed in the forward direction.
|
||||
* Singly-linked tail queues are ideal for applications with large datasets
|
||||
* and few or no removals or for implementing a FIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may be traversed in either direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*
|
||||
*
|
||||
* SLIST LIST STAILQ TAILQ
|
||||
* _HEAD + + + +
|
||||
* _HEAD_INITIALIZER + + + +
|
||||
* _ENTRY + + + +
|
||||
* _INIT + + + +
|
||||
* _EMPTY + + + +
|
||||
* _FIRST + + + +
|
||||
* _NEXT + + + +
|
||||
* _PREV - + - +
|
||||
* _LAST - - + +
|
||||
* _FOREACH + + + +
|
||||
* _FOREACH_FROM + + + +
|
||||
* _FOREACH_SAFE + + + +
|
||||
* _FOREACH_FROM_SAFE + + + +
|
||||
* _FOREACH_REVERSE - - - +
|
||||
* _FOREACH_REVERSE_FROM - - - +
|
||||
* _FOREACH_REVERSE_SAFE - - - +
|
||||
* _FOREACH_REVERSE_FROM_SAFE - - - +
|
||||
* _INSERT_HEAD + + + +
|
||||
* _INSERT_BEFORE - + - +
|
||||
* _INSERT_AFTER + + + +
|
||||
* _INSERT_TAIL - - + +
|
||||
* _CONCAT - - + +
|
||||
* _REMOVE_AFTER + - + -
|
||||
* _REMOVE_HEAD + - + -
|
||||
* _REMOVE + + + +
|
||||
* _SWAP + + + +
|
||||
*
|
||||
*/
|
||||
#ifdef QUEUE_MACRO_DEBUG
|
||||
/* Store the last 2 places the queue element or head was altered */
|
||||
struct qm_trace {
|
||||
unsigned long lastline;
|
||||
unsigned long prevline;
|
||||
const char *lastfile;
|
||||
const char *prevfile;
|
||||
};
|
||||
|
||||
#define TRACEBUF struct qm_trace trace;
|
||||
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
|
||||
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
|
||||
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
|
||||
|
||||
#define QMD_TRACE_HEAD(head) do { \
|
||||
(head)->trace.prevline = (head)->trace.lastline; \
|
||||
(head)->trace.prevfile = (head)->trace.lastfile; \
|
||||
(head)->trace.lastline = __LINE__; \
|
||||
(head)->trace.lastfile = __FILE__; \
|
||||
} while (0)
|
||||
|
||||
#define QMD_TRACE_ELEM(elem) do { \
|
||||
(elem)->trace.prevline = (elem)->trace.lastline; \
|
||||
(elem)->trace.prevfile = (elem)->trace.lastfile; \
|
||||
(elem)->trace.lastline = __LINE__; \
|
||||
(elem)->trace.lastfile = __FILE__; \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define QMD_TRACE_ELEM(elem)
|
||||
#define QMD_TRACE_HEAD(head)
|
||||
#define QMD_SAVELINK(name, link)
|
||||
#define TRACEBUF
|
||||
#define TRACEBUF_INITIALIZER
|
||||
#define TRASHIT(x)
|
||||
#endif /* QUEUE_MACRO_DEBUG */
|
||||
|
||||
/*
|
||||
* Singly-linked List declarations.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_FOREACH_FROM(var, head, field) \
|
||||
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
|
||||
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
|
||||
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
|
||||
for ((varp) = &SLIST_FIRST((head)); \
|
||||
((var) = *(varp)) != NULL; \
|
||||
(varp) = &SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_INIT(head) do { \
|
||||
SLIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
|
||||
SLIST_NEXT((slistelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
|
||||
SLIST_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
|
||||
if (SLIST_FIRST((head)) == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = SLIST_FIRST((head)); \
|
||||
while (SLIST_NEXT(curelm, field) != (elm)) \
|
||||
curelm = SLIST_NEXT(curelm, field); \
|
||||
SLIST_REMOVE_AFTER(curelm, field); \
|
||||
} \
|
||||
TRASHIT(*oldnext); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_AFTER(elm, field) do { \
|
||||
SLIST_NEXT(elm, field) = \
|
||||
SLIST_NEXT(SLIST_NEXT(elm, field), field); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_SWAP(head1, head2, type) do { \
|
||||
struct type *swap_first = SLIST_FIRST(head1); \
|
||||
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
|
||||
SLIST_FIRST(head2) = swap_first; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first;/* first element */ \
|
||||
struct type **stqh_last;/* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).stqh_first }
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue functions.
|
||||
*/
|
||||
#define STAILQ_CONCAT(head1, head2) do { \
|
||||
if (!STAILQ_EMPTY((head2))) { \
|
||||
*(head1)->stqh_last = (head2)->stqh_first; \
|
||||
(head1)->stqh_last = (head2)->stqh_last; \
|
||||
STAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for((var) = STAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_FOREACH_FROM(var, head, field) \
|
||||
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = STAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
|
||||
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
|
||||
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define STAILQ_INIT(head) do { \
|
||||
STAILQ_FIRST((head)) = NULL; \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_NEXT((tqelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
STAILQ_NEXT((elm), field) = NULL; \
|
||||
*(head)->stqh_last = (elm); \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_LAST(head, type, field) \
|
||||
(STAILQ_EMPTY((head)) ? NULL : \
|
||||
__containerof((head)->stqh_last, struct type, field.stqe_next))
|
||||
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
|
||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = STAILQ_FIRST((head)); \
|
||||
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
STAILQ_REMOVE_AFTER(head, curelm, field); \
|
||||
} \
|
||||
TRASHIT(*oldnext); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT(elm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_SWAP(head1, head2, type) do { \
|
||||
struct type *swap_first = STAILQ_FIRST(head1); \
|
||||
struct type **swap_last = (head1)->stqh_last; \
|
||||
STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
|
||||
(head1)->stqh_last = (head2)->stqh_last; \
|
||||
STAILQ_FIRST(head2) = swap_first; \
|
||||
(head2)->stqh_last = swap_last; \
|
||||
if (STAILQ_EMPTY(head1)) \
|
||||
(head1)->stqh_last = &STAILQ_FIRST(head1); \
|
||||
if (STAILQ_EMPTY(head2)) \
|
||||
(head2)->stqh_last = &STAILQ_FIRST(head2); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* List declarations.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
|
||||
#if (defined(_KERNEL) && defined(INVARIANTS))
|
||||
#define QMD_LIST_CHECK_HEAD(head, field) do { \
|
||||
if (LIST_FIRST((head)) != NULL && \
|
||||
LIST_FIRST((head))->field.le_prev != \
|
||||
&LIST_FIRST((head))) \
|
||||
panic("Bad list head %p first->prev != head", (head)); \
|
||||
} while (0)
|
||||
|
||||
#define QMD_LIST_CHECK_NEXT(elm, field) do { \
|
||||
if (LIST_NEXT((elm), field) != NULL && \
|
||||
LIST_NEXT((elm), field)->field.le_prev != \
|
||||
&((elm)->field.le_next)) \
|
||||
panic("Bad link elm %p next->prev != elm", (elm)); \
|
||||
} while (0)
|
||||
|
||||
#define QMD_LIST_CHECK_PREV(elm, field) do { \
|
||||
if (*(elm)->field.le_prev != (elm)) \
|
||||
panic("Bad link elm %p prev->next != elm", (elm)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define QMD_LIST_CHECK_HEAD(head, field)
|
||||
#define QMD_LIST_CHECK_NEXT(elm, field)
|
||||
#define QMD_LIST_CHECK_PREV(elm, field)
|
||||
#endif /* (_KERNEL && INVARIANTS) */
|
||||
|
||||
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_FOREACH_FROM(var, head, field) \
|
||||
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
|
||||
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
|
||||
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
QMD_LIST_CHECK_NEXT(listelm, field); \
|
||||
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
|
||||
LIST_NEXT((listelm), field)->field.le_prev = \
|
||||
&LIST_NEXT((elm), field); \
|
||||
LIST_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
QMD_LIST_CHECK_PREV(listelm, field); \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
LIST_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
QMD_LIST_CHECK_HEAD((head), field); \
|
||||
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
|
||||
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
|
||||
LIST_FIRST((head)) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_PREV(elm, head, type, field) \
|
||||
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
|
||||
__containerof((elm)->field.le_prev, struct type, field.le_next))
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
|
||||
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
|
||||
QMD_LIST_CHECK_NEXT(elm, field); \
|
||||
QMD_LIST_CHECK_PREV(elm, field); \
|
||||
if (LIST_NEXT((elm), field) != NULL) \
|
||||
LIST_NEXT((elm), field)->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||
TRASHIT(*oldnext); \
|
||||
TRASHIT(*oldprev); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_SWAP(head1, head2, type, field) do { \
|
||||
struct type *swap_tmp = LIST_FIRST((head1)); \
|
||||
LIST_FIRST((head1)) = LIST_FIRST((head2)); \
|
||||
LIST_FIRST((head2)) = swap_tmp; \
|
||||
if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
|
||||
swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
|
||||
if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
|
||||
swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Tail queue declarations.
|
||||
*/
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
TRACEBUF \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
TRACEBUF \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#if (defined(_KERNEL) && defined(INVARIANTS))
|
||||
#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
|
||||
if (!TAILQ_EMPTY(head) && \
|
||||
TAILQ_FIRST((head))->field.tqe_prev != \
|
||||
&TAILQ_FIRST((head))) \
|
||||
panic("Bad tailq head %p first->prev != head", (head)); \
|
||||
} while (0)
|
||||
|
||||
#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
|
||||
if (*(head)->tqh_last != NULL) \
|
||||
panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
|
||||
} while (0)
|
||||
|
||||
#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
|
||||
if (TAILQ_NEXT((elm), field) != NULL && \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev != \
|
||||
&((elm)->field.tqe_next)) \
|
||||
panic("Bad link elm %p next->prev != elm", (elm)); \
|
||||
} while (0)
|
||||
|
||||
#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
|
||||
if (*(elm)->field.tqe_prev != (elm)) \
|
||||
panic("Bad link elm %p prev->next != elm", (elm)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define QMD_TAILQ_CHECK_HEAD(head, field)
|
||||
#define QMD_TAILQ_CHECK_TAIL(head, headname)
|
||||
#define QMD_TAILQ_CHECK_NEXT(elm, field)
|
||||
#define QMD_TAILQ_CHECK_PREV(elm, field)
|
||||
#endif /* (_KERNEL && INVARIANTS) */
|
||||
|
||||
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||
if (!TAILQ_EMPTY(head2)) { \
|
||||
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
|
||||
(head1)->tqh_last = (head2)->tqh_last; \
|
||||
TAILQ_INIT((head2)); \
|
||||
QMD_TRACE_HEAD(head1); \
|
||||
QMD_TRACE_HEAD(head2); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_FROM(var, head, field) \
|
||||
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
|
||||
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
|
||||
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
|
||||
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
|
||||
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
|
||||
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_INIT(head) do { \
|
||||
TAILQ_FIRST((head)) = NULL; \
|
||||
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
QMD_TAILQ_CHECK_NEXT(listelm, field); \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else { \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} \
|
||||
TAILQ_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
QMD_TRACE_ELEM(&listelm->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
QMD_TAILQ_CHECK_PREV(listelm, field); \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
TAILQ_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
QMD_TRACE_ELEM(&listelm->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
QMD_TAILQ_CHECK_HEAD(head, field); \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
|
||||
TAILQ_FIRST((head))->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_FIRST((head)) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
QMD_TAILQ_CHECK_TAIL(head, field); \
|
||||
TAILQ_NEXT((elm), field) = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
|
||||
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
|
||||
QMD_TAILQ_CHECK_NEXT(elm, field); \
|
||||
QMD_TAILQ_CHECK_PREV(elm, field); \
|
||||
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else { \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} \
|
||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||
TRASHIT(*oldnext); \
|
||||
TRASHIT(*oldprev); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_SWAP(head1, head2, type, field) do { \
|
||||
struct type *swap_first = (head1)->tqh_first; \
|
||||
struct type **swap_last = (head1)->tqh_last; \
|
||||
(head1)->tqh_first = (head2)->tqh_first; \
|
||||
(head1)->tqh_last = (head2)->tqh_last; \
|
||||
(head2)->tqh_first = swap_first; \
|
||||
(head2)->tqh_last = swap_last; \
|
||||
if ((swap_first = (head1)->tqh_first) != NULL) \
|
||||
swap_first->field.tqe_prev = &(head1)->tqh_first; \
|
||||
else \
|
||||
(head1)->tqh_last = &(head1)->tqh_first; \
|
||||
if ((swap_first = (head2)->tqh_first) != NULL) \
|
||||
swap_first->field.tqe_prev = &(head2)->tqh_first; \
|
||||
else \
|
||||
(head2)->tqh_last = &(head2)->tqh_first; \
|
||||
} while (0)
|
||||
|
||||
#endif /* !_SYS_QUEUE_H_ */
|
84
include/xlsxwriter/utility.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file utility.h
|
||||
*
|
||||
* @brief Utility functions for libxlsxwriter.
|
||||
*
|
||||
* <!-- Copyright 2014, John McNamara, jmcnamara@cpan.org -->
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LXW_UTILITY_H__
|
||||
#define __LXW_UTILITY_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common.h"
|
||||
|
||||
#define MAX_COL_NAME_LENGTH 5
|
||||
#define MAX_CELL_NAME_LENGTH 13
|
||||
#define MAX_CELL_RANGE_LENGTH (MAX_CELL_NAME_LENGTH * 2 + 1)
|
||||
#define EPOCH_1900 0
|
||||
#define EPOCH_1904 1
|
||||
|
||||
/** @brief Struct to represent a date and time in Excel.
|
||||
*
|
||||
* Struct to represent a date and time in Excel. See @ref working_with_dates.
|
||||
*/
|
||||
typedef struct lxw_datetime {
|
||||
|
||||
/** Year : 1900 - 9999 */
|
||||
int year;
|
||||
/** Month : 1 - 12 */
|
||||
int month;
|
||||
/** Day : 1 - 31 */
|
||||
int day;
|
||||
/** Hour : 0 - 23 */
|
||||
int hour;
|
||||
/** Minute : 0 - 59 */
|
||||
int min;
|
||||
/** Seconds : 0 - 59.999 */
|
||||
double sec;
|
||||
|
||||
} lxw_datetime;
|
||||
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
void _xl_col_to_name(char *col_name, int col_num, uint8_t absolute);
|
||||
|
||||
void xl_rowcol_to_cell(char *cell_name, int row, int col);
|
||||
|
||||
void xl_rowcol_to_cell_abs(char *cell_name,
|
||||
int row,
|
||||
int col, uint8_t abs_row, uint8_t abs_col);
|
||||
|
||||
void xl_range(char *range,
|
||||
int first_row, int first_col, int last_row, int last_col);
|
||||
|
||||
void xl_range_abs(char *range,
|
||||
int first_row, int first_col, int last_row, int last_col);
|
||||
|
||||
double _datetime_to_excel_date(lxw_datetime *datetime, uint8_t date_1904);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_UTILITY_H__ */
|
244
include/xlsxwriter/workbook.h
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page workbook_page The Workbook object
|
||||
*
|
||||
* The Workbook is the main object exposed by the libxlsxwriter library. It
|
||||
* represents the entire spreadsheet as you see it in Excel and internally it
|
||||
* represents the Excel file as it is written on disk.
|
||||
*
|
||||
* See @ref workbook.h for full details of the functionality.
|
||||
*
|
||||
* @file workbook.h
|
||||
*
|
||||
* @brief Functions related to creating an Excel xlsx workbook.
|
||||
*
|
||||
* The Workbook is the main object exposed by the libxlsxwriter library. It
|
||||
* represents the entire spreadsheet as you see it in Excel and internally it
|
||||
* represents the Excel file as it is written on disk.
|
||||
*
|
||||
* @code
|
||||
* #include "xlsxwriter.h"
|
||||
*
|
||||
* int main() {
|
||||
*
|
||||
* lxw_workbook *workbook = new_workbook("filename.xlsx");
|
||||
* lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
*
|
||||
* worksheet_write_string(worksheet, 0, 0, "Hello Excel", NULL);
|
||||
*
|
||||
* return workbook_close(workbook);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @image html workbook01.png
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_WORKBOOK_H__
|
||||
#define __LXW_WORKBOOK_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
|
||||
#include "worksheet.h"
|
||||
#include "shared_strings.h"
|
||||
#include "hash_table.h"
|
||||
#include "common.h"
|
||||
|
||||
/* Define the queue.h TAILQ structs for the workbook list. */
|
||||
STAILQ_HEAD(lxw_worksheets, lxw_worksheet);
|
||||
|
||||
/**
|
||||
* @brief Errors conditions encountered when closing the Workbook and writing
|
||||
* the Excel file to disk.
|
||||
*/
|
||||
enum lxw_close_error {
|
||||
/** No error */
|
||||
LXW_CLOSE_ERROR_NONE,
|
||||
/** Error encountered when creating file zip container */
|
||||
LXW_CLOSE_ERROR_ZIP
|
||||
/* TODO. Need to add/document more. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Struct to represent an Excel workbook.
|
||||
*
|
||||
* The members of the lxw_workbook struct aren't modified directly. Instead
|
||||
* the workbook properties are set by calling the functions shown in
|
||||
* workbook.h.
|
||||
*/
|
||||
typedef struct lxw_workbook {
|
||||
|
||||
FILE *file;
|
||||
struct lxw_worksheets *worksheets;
|
||||
struct lxw_formats *formats;
|
||||
lxw_sst *sst;
|
||||
lxw_doc_properties *properties;
|
||||
const char *filename;
|
||||
|
||||
uint16_t num_sheets;
|
||||
uint16_t first_sheet;
|
||||
uint16_t active_tab;
|
||||
uint16_t num_xf_formats;
|
||||
uint16_t num_format_count;
|
||||
|
||||
uint16_t font_count;
|
||||
uint16_t border_count;
|
||||
uint16_t fill_count;
|
||||
|
||||
lxw_hash_table *xf_format_indices;
|
||||
|
||||
} lxw_workbook;
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* @brief Create a new workbook object.
|
||||
*
|
||||
* @param filename The name of the new Excel file to create.
|
||||
*
|
||||
* @return A lxw_workbook instance.
|
||||
*
|
||||
* The `%new_workbook()` constructor is used to create a new Excel workbook
|
||||
* with a given filename:
|
||||
*
|
||||
* @code
|
||||
* lxw_workbook *workbook = new_workbook("filename.xlsx");
|
||||
* @endcode
|
||||
*
|
||||
* When specifying a filename it is recommended that you use an `.xlsx`
|
||||
* extension or Excel will generate a warning when opening the file.
|
||||
*
|
||||
*/
|
||||
lxw_workbook *new_workbook(const char *filename);
|
||||
|
||||
/**
|
||||
* @brief Add a new worksheet to a workbook:
|
||||
*
|
||||
* @param workbook Pointer to a lxw_workbook instance.
|
||||
* @param sheetname Optional worksheet name, defaults to Sheet1, etc.
|
||||
*
|
||||
* @return A lxw_worksheet instance.
|
||||
*
|
||||
* The `%workbook_add_worksheet()` method adds a new worksheet to a workbook:
|
||||
*
|
||||
* At least one worksheet should be added to a new workbook: The @ref
|
||||
* worksheet.h "Worksheet" object is used to write data and configure a
|
||||
* worksheet in the workbook.
|
||||
*
|
||||
* The `sheetname` parameter is optional. If it is `NULL` the default
|
||||
* Excel convention will be followed, i.e. Sheet1, Sheet2, etc.:
|
||||
*
|
||||
* @code
|
||||
* worksheet = workbook_add_worksheet(workbook, NULL ); // Sheet1
|
||||
* worksheet = workbook_add_worksheet(workbook, "Foglio2"); // Foglio2
|
||||
* worksheet = workbook_add_worksheet(workbook, "Data"); // Data
|
||||
* worksheet = workbook_add_worksheet(workbook, NULL ); // Sheet4
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @image html workbook02.png
|
||||
*
|
||||
* The worksheet name must be a valid Excel worksheet name, i.e. it must be
|
||||
* less than 32 character and it cannot contain any of the characters:
|
||||
*
|
||||
* / \ [ ] : * ?
|
||||
*
|
||||
* In addition, you cannot use the same, case insensitive, `sheetname` for more
|
||||
* than one worksheet.
|
||||
*
|
||||
*/
|
||||
lxw_worksheet *workbook_add_worksheet(lxw_workbook *workbook,
|
||||
const char *sheetname);
|
||||
|
||||
/**
|
||||
* @brief Create a new @ref format.h "Format" object to formats cells in
|
||||
* worksheets.
|
||||
*
|
||||
* @param workbook Pointer to a lxw_workbook instance.
|
||||
*
|
||||
* @return A lxw_format instance.
|
||||
*
|
||||
* The `workbook_add_format()` function can be used to create new @ref
|
||||
* format.h "Format" objects which are used to apply formatting to a cell.
|
||||
*
|
||||
* @code
|
||||
* // Create the Format.
|
||||
* lxw_format *format = workbook_add_format(workbook);
|
||||
*
|
||||
* // Set some of the format properties.
|
||||
* format_set_bold(format);
|
||||
* format_set_font_color(format, LXW_COLOR_RED);
|
||||
*
|
||||
* // Use the format to change the text format in a cell.
|
||||
* worksheet_write_string(worksheet, 0, 0, "Hello", format);
|
||||
* @endcode
|
||||
*
|
||||
* See @ref format.h "the Format object" and @ref working_with_formats
|
||||
* sections for more details about Format properties and how to set them.
|
||||
*
|
||||
*/
|
||||
lxw_format *workbook_add_format(lxw_workbook *workbook);
|
||||
|
||||
/**
|
||||
* @brief Close the Workbook object and write the XLSX file.
|
||||
*
|
||||
* @param workbook Pointer to a lxw_workbook instance.
|
||||
*
|
||||
* @return A #lxw_close_error.
|
||||
*
|
||||
* The `%workbook_close()` function closes a Workbook object, writes the Excel
|
||||
* file to disk, frees any memory allocated internally to the Workbook and
|
||||
* frees the object itself.
|
||||
*
|
||||
* @code
|
||||
* workbook_close(workbook);
|
||||
* @endcode
|
||||
*
|
||||
* The `%workbook_close()` function returns any #lxw_close_error error codes
|
||||
* encountered when creating the Excel file. The error code can be returned
|
||||
* from the program main or the calling function:
|
||||
*
|
||||
* @code
|
||||
* return workbook_close(workbook);
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
uint8_t workbook_close(lxw_workbook *workbook);
|
||||
|
||||
void _free_workbook(lxw_workbook *workbook);
|
||||
void _workbook_assemble_xml_file(lxw_workbook *self);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
STATIC void _workbook_xml_declaration(lxw_workbook *self);
|
||||
STATIC void _workbook_xml_declaration(lxw_workbook *self);
|
||||
STATIC void _write_workbook(lxw_workbook *self);
|
||||
STATIC void _write_file_version(lxw_workbook *self);
|
||||
STATIC void _write_workbook_pr(lxw_workbook *self);
|
||||
STATIC void _write_book_views(lxw_workbook *self);
|
||||
STATIC void _write_workbook_view(lxw_workbook *self);
|
||||
STATIC void _write_sheet(lxw_workbook *self,
|
||||
const char *name, uint32_t sheet_id, uint8_t hidden);
|
||||
STATIC void _write_sheets(lxw_workbook *self);
|
||||
STATIC void _write_calc_pr(lxw_workbook *self);
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_WORKBOOK_H__ */
|
430
include/xlsxwriter/worksheet.h
Normal file
@ -0,0 +1,430 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page worksheet_page The Worksheet object
|
||||
*
|
||||
* The Worksheet object represents an Excel worksheet. It handles
|
||||
* operations such as writing data to cells or formatting worksheet
|
||||
* layout.
|
||||
*
|
||||
* See @ref worksheet.h for full details of the functionality.
|
||||
*
|
||||
* @file worksheet.h
|
||||
*
|
||||
* @brief Functions related to adding data and formatting to a worksheet.
|
||||
*
|
||||
* The Worksheet object represents an Excel worksheet. It handles
|
||||
* operations such as writing data to cells or formatting worksheet
|
||||
* layout.
|
||||
*
|
||||
* A Worksheet object isn’t created directly. Instead a worksheet is
|
||||
* created by calling the workbook_add_worksheet() method from a
|
||||
* Workbook object:
|
||||
*
|
||||
* @code
|
||||
* #include "xlsxwriter.h"
|
||||
*
|
||||
* int main() {
|
||||
*
|
||||
* lxw_workbook *workbook = new_workbook("filename.xlsx");
|
||||
* lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
*
|
||||
* worksheet_write_string(worksheet, 0, 0, "Hello Excel", NULL);
|
||||
*
|
||||
* return workbook_close(workbook);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_WORKSHEET_H__
|
||||
#define __LXW_WORKSHEET_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "shared_strings.h"
|
||||
#include "common.h"
|
||||
#include "format.h"
|
||||
#include "utility.h"
|
||||
|
||||
/** @brief Error codes from `worksheet_write*()` functions. */
|
||||
enum lxw_write_error {
|
||||
LXW_WRITE_ERROR_NONE = 0,
|
||||
LXW_RANGE_ERROR,
|
||||
LXW_STRING_HASH_ERROR,
|
||||
LXW_STRING_LENGTH_ERROR,
|
||||
LXW_END
|
||||
};
|
||||
|
||||
enum cell_types {
|
||||
NUMBER_CELL = 1,
|
||||
STRING_CELL,
|
||||
FORMULA_CELL,
|
||||
BLANK_CELL
|
||||
};
|
||||
|
||||
/* Define the queue.h TAILQ structs for the list head types. */
|
||||
TAILQ_HEAD(lxw_table_cells, lxw_cell);
|
||||
TAILQ_HEAD(lxw_table_rows, lxw_row);
|
||||
|
||||
/**
|
||||
* @brief Struct to represent an Excel worksheet.
|
||||
*
|
||||
* The members of the lxw_worksheet struct aren't modified directly. Instead
|
||||
* the worksheet properties are set by calling the functions shown in
|
||||
* worksheet.h.
|
||||
*/
|
||||
typedef struct lxw_worksheet {
|
||||
|
||||
FILE *file;
|
||||
struct lxw_table_rows *table;
|
||||
|
||||
uint32_t dim_rowmin;
|
||||
uint32_t dim_rowmax;
|
||||
uint16_t dim_colmin;
|
||||
uint16_t dim_colmax;
|
||||
|
||||
lxw_sst *sst;
|
||||
char *name;
|
||||
|
||||
uint32_t index;
|
||||
uint8_t active;
|
||||
uint8_t selected;
|
||||
uint8_t hidden;
|
||||
|
||||
STAILQ_ENTRY (lxw_worksheet) list_pointers;
|
||||
|
||||
} lxw_worksheet;
|
||||
|
||||
/*
|
||||
* Worksheet initialisation data.
|
||||
*/
|
||||
typedef struct lxw_worksheet_init_data {
|
||||
uint32_t index;
|
||||
uint8_t hidden;
|
||||
|
||||
lxw_sst *sst;
|
||||
char *name;
|
||||
|
||||
} lxw_worksheet_init_data;
|
||||
|
||||
/* Struct to represent a worksheet row. */
|
||||
typedef struct lxw_row {
|
||||
uint32_t row_num;
|
||||
struct lxw_table_cells *cells;
|
||||
|
||||
/* List pointers for queue.h. */
|
||||
TAILQ_ENTRY (lxw_row) list_pointers;
|
||||
} lxw_row;
|
||||
|
||||
/* Struct to represent a worksheet cell. */
|
||||
typedef struct lxw_cell {
|
||||
uint32_t row_num;
|
||||
uint16_t col_num;
|
||||
enum cell_types type;
|
||||
lxw_format *format;
|
||||
|
||||
union {
|
||||
double number;
|
||||
int32_t string_id;
|
||||
char *formula;
|
||||
} u;
|
||||
|
||||
union {
|
||||
double number;
|
||||
char *string;
|
||||
} formula_result;
|
||||
|
||||
/* List pointers for queue.h. */
|
||||
TAILQ_ENTRY (lxw_cell) list_pointers;
|
||||
} lxw_cell;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* @brief Write a number to a worksheet cell.
|
||||
*
|
||||
* @param worksheet Pointer to the lxw_worksheet instance to be updated.
|
||||
* @param row The zero indexed row number.
|
||||
* @param col The zero indexed column number.
|
||||
* @param number The number to write to the cell.
|
||||
* @param format A pointer to a Format instance or NULL.
|
||||
*
|
||||
* @return A #lxw_write_error code.
|
||||
*
|
||||
* The `worksheet_write_number()` method writes numeric types to the cell specified by
|
||||
* `row` and `column`:
|
||||
*
|
||||
* @code
|
||||
* worksheet_write_number(worksheet, 0, 0, 123456, NULL);
|
||||
* worksheet_write_number(worksheet, 1, 0, 2.3451, NULL);
|
||||
* @endcode
|
||||
*
|
||||
* @image html write_number01.png
|
||||
*
|
||||
* The native data type for all numbers in Excel is a IEEE-754 64-bit
|
||||
* double-precision floating point, which is also the default type used by
|
||||
* `%worksheet_write_number`.
|
||||
*
|
||||
* The `format` parameter is used to apply formatting to the cell. This
|
||||
* parameter can be `NULL` to indicate no formatting or it can be a
|
||||
* @ref format.h "Format" object.
|
||||
*
|
||||
* @code
|
||||
* lxw_format *format = workbook_add_format(workbook);
|
||||
* format_set_num_format(format, "$#,##0.00");
|
||||
*
|
||||
* worksheet_write_number(worksheet, 0, 0, 1234.567, format);
|
||||
* @endcode
|
||||
*
|
||||
* @image html write_number02.png
|
||||
*
|
||||
*/
|
||||
int8_t worksheet_write_number(lxw_worksheet *worksheet,
|
||||
uint32_t row,
|
||||
uint16_t col, double number,
|
||||
lxw_format *format);
|
||||
/**
|
||||
* @brief Write a string to a worksheet cell.
|
||||
*
|
||||
* @param worksheet Pointer to the lxw_worksheet instance to be updated.
|
||||
* @param row The zero indexed row number.
|
||||
* @param col The zero indexed column number.
|
||||
* @param string String to write to cell.
|
||||
* @param format A pointer to a Format instance or NULL.
|
||||
*
|
||||
* @return A #lxw_write_error code.
|
||||
*
|
||||
* The `%worksheet_write_string()` method writes a string to the cell specified by `row`
|
||||
* and `column`:
|
||||
*
|
||||
* @code
|
||||
* worksheet_write_string(worksheet, 0, 0, "This phrase is English!", NULL);
|
||||
* @endcode
|
||||
*
|
||||
* @image html write_string01.png
|
||||
*
|
||||
* The `format` parameter is used to apply formatting to the cell. This
|
||||
* parameter can be `NULL` to indicate no formatting or it can be a
|
||||
* @ref format.h "Format" object:
|
||||
*
|
||||
* @code
|
||||
* lxw_format *format = workbook_add_format(workbook);
|
||||
* format_set_bold(format);
|
||||
*
|
||||
* worksheet_write_string(worksheet, 0, 0, "This phrase is Bold!", format);
|
||||
* @endcode
|
||||
*
|
||||
* @image html write_string02.png
|
||||
*
|
||||
* Unicode strings are supported in UTF-8 encoding. This generally requires
|
||||
* that your source file is UTF-8 encoded or that the data has been read from
|
||||
* a UTF-8 source:
|
||||
*
|
||||
* @code
|
||||
* worksheet_write_string(worksheet, 0, 0, "Это фраза на русском!", NULL);
|
||||
* @endcode
|
||||
*
|
||||
* @image html write_string03.png
|
||||
*
|
||||
*/
|
||||
int8_t worksheet_write_string(lxw_worksheet *worksheet,
|
||||
uint32_t row,
|
||||
uint16_t col, const char *string,
|
||||
lxw_format *format);
|
||||
/**
|
||||
* @brief Write a formula to a worksheet cell.
|
||||
*
|
||||
* @param worksheet Pointer to the lxw_worksheet instance to be updated.
|
||||
* @param row The zero indexed row number.
|
||||
* @param col The zero indexed column number.
|
||||
* @param formula Formula string to write to cell.
|
||||
* @param format A pointer to a Format instance or NULL.
|
||||
*
|
||||
* @return A #lxw_write_error code.
|
||||
*
|
||||
* The `%worksheet_write_formula()` method writes a formula or function to the cell
|
||||
* specified by `row` and `column`:
|
||||
*
|
||||
* @code
|
||||
* worksheet_write_formula(worksheet, 0, 0, "=B3 + 6", NULL);
|
||||
* worksheet_write_formula(worksheet, 1, 0, "=SIN(PI()/4)", NULL);
|
||||
* worksheet_write_formula(worksheet, 2, 0, "=SUM(A1:A2)", NULL);
|
||||
* worksheet_write_formula(worksheet, 3, 0, "=IF(A3>1,\"Yes\", \"No\")", NULL);
|
||||
* worksheet_write_formula(worksheet, 4, 0, "=AVERAGE(1, 2, 3, 4)", NULL);
|
||||
* worksheet_write_formula(worksheet, 5, 0, "=DATEVALUE(\"1-Jan-2013\")", NULL);
|
||||
* @endcode
|
||||
*
|
||||
* @image html write_formula01.png
|
||||
*
|
||||
* The `format` parameter is used to apply formatting to the cell. This
|
||||
* parameter can be `NULL` to indicate no formatting or it can be a
|
||||
* @ref format.h "Format" object.
|
||||
*
|
||||
* Libxlsxwriter doesn't calculate the value of a formula and instead stores a
|
||||
* default value of `0`. The correct formula result is displayed in Excel, as
|
||||
* shown in the example above, since it recalculates the formulas when it loads
|
||||
* the file. For cases where this is an issue see the
|
||||
* `worksheet_write_formula_num()` function and the discussion in that section.
|
||||
*
|
||||
* Formulas must be written with the US style separator/range operator which
|
||||
* is a comma (not semi-colon). Therefore a formula with multiple values
|
||||
* should be written as follows:
|
||||
*
|
||||
* @code
|
||||
* worksheet_write_formula(worksheet, 0, 0, "=SUM(1, 2, 3)", NULL); // OK.
|
||||
* worksheet_write_formula(worksheet, 1, 0, "=SUM(1; 2; 3)", NULL); // NO. Error on load.
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
int8_t worksheet_write_formula(lxw_worksheet *worksheet,
|
||||
uint32_t row,
|
||||
uint16_t col, const char *formula,
|
||||
lxw_format *format);
|
||||
/**
|
||||
* @brief Write a formula to a worksheet cell with a user defined result.
|
||||
*
|
||||
* @param worksheet Pointer to the lxw_worksheet instance to be updated.
|
||||
* @param row The zero indexed row number.
|
||||
* @param col The zero indexed column number.
|
||||
* @param formula Formula string to write to cell.
|
||||
* @param format A pointer to a Format instance or NULL.
|
||||
* @param result A user defined result for a formula.
|
||||
*
|
||||
* @return A #lxw_write_error code.
|
||||
*
|
||||
* The `%worksheet_write_formula_num()` method writes a formula or function to the cell
|
||||
* specified by `row` and `column` with a user defined result:
|
||||
*
|
||||
* @code
|
||||
* // Required as a workaround only.
|
||||
* worksheet_write_formula_num(worksheet, 0, 0, "=1 + 2", NULL, 3);
|
||||
* @endcode
|
||||
*
|
||||
* Libxlsxwriter doesn't calculate the value of a formula and instead stores
|
||||
* the value `0` as the formula result. It then sets a global flag in the XLSX
|
||||
* file to say that all formulas and functions should be recalculated when the
|
||||
* file is opened.
|
||||
*
|
||||
* This is the method recommended in the Excel documentation and in general it
|
||||
* works fine with spreadsheet applications.
|
||||
*
|
||||
* However, applications that don't have a facility to calculate formulas,
|
||||
* such as Excel Viewer, or some mobile applications will only display the `0`
|
||||
* results.
|
||||
*
|
||||
* If required, the `%worksheet_write_formula_num()` function can be used to
|
||||
* specify a formula and its result.
|
||||
*
|
||||
* This function is rarely required and is only provided for compatibility
|
||||
* with some third party applications. For most applications the
|
||||
* worksheet_write_formula() function is the recommended way of writing
|
||||
* formulas.
|
||||
*
|
||||
*/
|
||||
int8_t worksheet_write_formula_num(lxw_worksheet *worksheet,
|
||||
uint32_t row,
|
||||
uint16_t col,
|
||||
const char *formula,
|
||||
lxw_format *format, double result);
|
||||
|
||||
/**
|
||||
* @brief Write a date or time to a worksheet cell.
|
||||
*
|
||||
* @param worksheet Pointer to the lxw_worksheet instance to be updated.
|
||||
* @param row The zero indexed row number.
|
||||
* @param col The zero indexed column number.
|
||||
* @param datetime The datetime to write to the cell.
|
||||
* @param format A pointer to a Format instance or NULL.
|
||||
*
|
||||
* @return A #lxw_write_error code.
|
||||
*
|
||||
* The `worksheet_write_datetime()` method can be used to write a date or time to the cell
|
||||
* specified by `row` and `column`:
|
||||
*
|
||||
* @dontinclude dates_and_times02.c
|
||||
* @skip include
|
||||
* @until num_format
|
||||
* @skip Feb
|
||||
* @until }
|
||||
*
|
||||
* The `format` parameter should be used to apply formatting to the cell using
|
||||
* a @ref format.h "Format" object as shown above. Without a date format the
|
||||
* datetime will appear as a number only.
|
||||
*
|
||||
* See @ref working_with_dates for more information about handling dates and
|
||||
* times in libxlsxwriter.
|
||||
*/
|
||||
int8_t worksheet_write_datetime(lxw_worksheet *worksheet,
|
||||
uint32_t row,
|
||||
uint16_t col, lxw_datetime *datetime,
|
||||
lxw_format *format);
|
||||
|
||||
/**
|
||||
* @brief Write a formatted blank worksheet cell.
|
||||
*
|
||||
* @param worksheet Pointer to the lxw_worksheet instance to be updated.
|
||||
* @param row The zero indexed row number.
|
||||
* @param col The zero indexed column number.
|
||||
* @param format A pointer to a Format instance or NULL.
|
||||
*
|
||||
* @return A #lxw_write_error code.
|
||||
*
|
||||
* Write a blank cell specified by `row` and `column`:
|
||||
*
|
||||
* @code
|
||||
* worksheet_write_blank(worksheet, 1, 1, border_format);
|
||||
* @endcode
|
||||
*
|
||||
* This method is used to add formatting to a cell which doesn't contain a string
|
||||
* or number value.
|
||||
*
|
||||
* Excel differentiates between an "Empty" cell and a "Blank" cell. An Empty
|
||||
* cell is a cell which doesn't contain data or formatting whilst a Blank cell
|
||||
* doesn't contain data but does contain formatting. Excel stores Blank cells
|
||||
* but ignores Empty cells.
|
||||
*
|
||||
* As such, if you write an empty cell without formatting it is ignored.
|
||||
*
|
||||
*/
|
||||
|
||||
int8_t worksheet_write_blank(lxw_worksheet *worksheet,
|
||||
uint32_t row, uint16_t col, lxw_format *format);
|
||||
|
||||
lxw_worksheet *_new_worksheet(lxw_worksheet_init_data *init_data);
|
||||
void _free_worksheet(lxw_worksheet *worksheet);
|
||||
void _worksheet_assemble_xml_file(lxw_worksheet *worksheet);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
STATIC void _worksheet_xml_declaration(lxw_worksheet *worksheet);
|
||||
STATIC void _worksheet_write_worksheet(lxw_worksheet *worksheet);
|
||||
STATIC void _worksheet_write_dimension(lxw_worksheet *worksheet);
|
||||
STATIC void _worksheet_write_sheet_view(lxw_worksheet *worksheet);
|
||||
STATIC void _worksheet_write_sheet_views(lxw_worksheet *worksheet);
|
||||
STATIC void _worksheet_write_sheet_format_pr(lxw_worksheet *worksheet);
|
||||
STATIC void _worksheet_write_sheet_data(lxw_worksheet *worksheet);
|
||||
STATIC void _worksheet_write_page_margins(lxw_worksheet *worksheet);
|
||||
STATIC void _write_row(lxw_worksheet *worksheet, lxw_row *row, char *spans);
|
||||
STATIC lxw_row *_get_row(struct lxw_table_rows *table, uint32_t row_num);
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_WORKSHEET_H__ */
|
166
include/xlsxwriter/xmlwriter.h
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
* xmlwriter - A libxlsxwriter library for creating Excel XLSX
|
||||
* XML files.
|
||||
*
|
||||
* The xmlwriter library is used to create the XML sub-components files
|
||||
* in the Excel XLSX file format.
|
||||
*
|
||||
* This library is used in preference to a more generic XML library to allow
|
||||
* for customisation and optimisation for the XLSX file format.
|
||||
*
|
||||
* The xmlwriter functions are only used internally and do not need to be
|
||||
* called directly by the end user.
|
||||
*
|
||||
*/
|
||||
#ifndef __XMLWRITER_H__
|
||||
#define __XMLWRITER_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "xlsxwriter/third_party/queue.h"
|
||||
|
||||
/* Defines. */
|
||||
#define MAX_ATTRIBUTE_LENGTH 140
|
||||
#define ATTR_32 32
|
||||
#define MAX_CELL_NAME_LENGTH 13
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* Attribute used in XML elements. */
|
||||
struct xml_attribute {
|
||||
char key[MAX_ATTRIBUTE_LENGTH];
|
||||
char value[MAX_ATTRIBUTE_LENGTH];
|
||||
|
||||
/* Make the struct a queue.h list element. */
|
||||
STAILQ_ENTRY (xml_attribute) list_entries;
|
||||
};
|
||||
|
||||
/* Use queue.h macros to define the xml_attribute_list type. */
|
||||
STAILQ_HEAD(xml_attribute_list, xml_attribute);
|
||||
|
||||
/* Create a new attribute struct to add to a xml_attribute_list. */
|
||||
struct xml_attribute *_new_attribute_str(const char *key, const char *value);
|
||||
struct xml_attribute *_new_attribute_int(const char *key, uint32_t value);
|
||||
struct xml_attribute *_new_attribute_dbl(const char *key, double value);
|
||||
|
||||
/* Macro to initialise the xml_attribute_list pointers. */
|
||||
#define _INIT_ATTRIBUTES() \
|
||||
STAILQ_INIT(&attributes)
|
||||
|
||||
/* Macro to add attribute string elements to xml_attribute_list. */
|
||||
#define _PUSH_ATTRIBUTES_STR(key, value) \
|
||||
do { \
|
||||
attribute = _new_attribute_str((key), (value)); \
|
||||
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
|
||||
} while (0)
|
||||
|
||||
/* Macro to add attribute int values to xml_attribute_list. */
|
||||
#define _PUSH_ATTRIBUTES_INT(key, value) \
|
||||
do { \
|
||||
attribute = _new_attribute_int((key), (value)); \
|
||||
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
|
||||
} while (0)
|
||||
|
||||
/* Macro to add attribute double values to xml_attribute_list. */
|
||||
#define _PUSH_ATTRIBUTES_FLT(key, value) \
|
||||
do { \
|
||||
attribute = _new_attribute_flt((key), (value)); \
|
||||
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
|
||||
} while (0)
|
||||
|
||||
/* Macro to free xml_attribute_list and attribute. */
|
||||
#define _FREE_ATTRIBUTES() \
|
||||
while (!STAILQ_EMPTY(&attributes)) { \
|
||||
attribute = STAILQ_FIRST(&attributes); \
|
||||
STAILQ_REMOVE_HEAD(&attributes, list_entries); \
|
||||
free(attribute); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the XML declaration in an XML file.
|
||||
*
|
||||
* @param xmlfile A FILE pointer to the output XML file.
|
||||
*/
|
||||
void _xml_declaration(FILE * xmlfile);
|
||||
|
||||
/**
|
||||
* Write an XML start tag with optional attributes.
|
||||
*
|
||||
* @param xmlfile A FILE pointer to the output XML file.
|
||||
* @param tag The XML tag to write.
|
||||
* @param attributes An optional list of attributes to add to the tag.
|
||||
*/
|
||||
void _xml_start_tag(FILE * xmlfile,
|
||||
const char *tag, struct xml_attribute_list *attributes);
|
||||
|
||||
/**
|
||||
* Write an XML start tag with optional un-encoded attributes.
|
||||
* This is a minor optimisation for attributes that don't need encoding.
|
||||
*
|
||||
* @param xmlfile A FILE pointer to the output XML file.
|
||||
* @param tag The XML tag to write.
|
||||
* @param attributes An optional list of attributes to add to the tag.
|
||||
*/
|
||||
void _xml_start_tag_unencoded(FILE * xmlfile,
|
||||
const char *tag,
|
||||
struct xml_attribute_list *attributes);
|
||||
|
||||
/**
|
||||
* Write an XML end tag.
|
||||
*
|
||||
* @param xmlfile A FILE pointer to the output XML file.
|
||||
* @param tag The XML tag to write.
|
||||
*/
|
||||
void _xml_end_tag(FILE * xmlfile, const char *tag);
|
||||
|
||||
/**
|
||||
* Write an XML empty tag with optional attributes.
|
||||
*
|
||||
* @param xmlfile A FILE pointer to the output XML file.
|
||||
* @param tag The XML tag to write.
|
||||
* @param attributes An optional list of attributes to add to the tag.
|
||||
*/
|
||||
void _xml_empty_tag(FILE * xmlfile,
|
||||
const char *tag, struct xml_attribute_list *attributes);
|
||||
|
||||
/**
|
||||
* Write an XML empty tag with optional un-encoded attributes.
|
||||
* This is a minor optimisation for attributes that don't need encoding.
|
||||
*
|
||||
* @param xmlfile A FILE pointer to the output XML file.
|
||||
* @param tag The XML tag to write.
|
||||
* @param attributes An optional list of attributes to add to the tag.
|
||||
*/
|
||||
void _xml_empty_tag_unencoded(FILE * xmlfile,
|
||||
const char *tag,
|
||||
struct xml_attribute_list *attributes);
|
||||
|
||||
/**
|
||||
* Write an XML element containing data and optional attributes.
|
||||
*
|
||||
* @param xmlfile A FILE pointer to the output XML file.
|
||||
* @param tag The XML tag to write.
|
||||
* @param data The data section of the XML element.
|
||||
* @param attributes An optional list of attributes to add to the tag.
|
||||
*/
|
||||
void _xml_data_element(FILE * xmlfile,
|
||||
const char *tag,
|
||||
const char *data,
|
||||
struct xml_attribute_list *attributes);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __XMLWRITER_H__ */
|
0
lib/.gitignore
vendored
Normal file
71
src/Makefile
Normal file
@ -0,0 +1,71 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Makefile for libxlsxwriter library.
|
||||
#
|
||||
# Copyright 2014, John McNamara, jmcnamara@cpan.org
|
||||
#
|
||||
|
||||
# Keep the output quiet by default.
|
||||
Q=@
|
||||
ifdef V
|
||||
Q=
|
||||
endif
|
||||
|
||||
# Directory variables.
|
||||
OBJS_DIR = .
|
||||
INC_DIR = ../include
|
||||
|
||||
# The minizip directory.
|
||||
MINIZIP_DIR = ../third_party/minizip
|
||||
|
||||
# Flags passed to compiler.
|
||||
CFLAGS += -g -O3 -Wall -Wextra -pedantic -ansi
|
||||
|
||||
# Library names.
|
||||
LIBXLSXWRITER_A = libxlsxwriter.a
|
||||
LIBXLSXWRITER_SO = libxlsxwriter.so
|
||||
|
||||
# Flags passed to static linker.
|
||||
ARFLAGS = rc
|
||||
|
||||
# Flags passed to dynamic linker.
|
||||
SOFLAGS = -shared -fPIC
|
||||
|
||||
# Change shared lib options on OS X.
|
||||
UNAME := $(shell uname)
|
||||
ifeq ($(UNAME), Darwin)
|
||||
LIBXLSXWRITER_SO = libxlsxwriter.dylib
|
||||
SOFLAGS = -dynamiclib -fPIC -install_name /usr/lib/$(LIBXLSXWRITER_SO)
|
||||
endif
|
||||
|
||||
|
||||
# Headers as dependecies.
|
||||
HDRS = $(wildcard ../include/xlsxwriter/*.h)
|
||||
|
||||
# Ojects to compile.
|
||||
SRCS = $(wildcard *.c)
|
||||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
SOBJS = $(patsubst %.c,%.so,$(SRCS))
|
||||
# End of OBJS
|
||||
|
||||
# Build the object files and the libraries.
|
||||
all : $(LIBXLSXWRITER_A) $(LIBXLSXWRITER_SO)
|
||||
$(Q)cp $(LIBXLSXWRITER_A) $(LIBXLSXWRITER_SO) ../lib
|
||||
|
||||
# The static library.
|
||||
$(LIBXLSXWRITER_A) : $(OBJS)
|
||||
$(Q)$(AR) $(ARFLAGS) $@ $(MINIZIP_DIR)/ioapi.o $(MINIZIP_DIR)/zip.o $^
|
||||
|
||||
$(LIBXLSXWRITER_SO) : $(SOBJS)
|
||||
$(Q)$(CC) $(SOFLAGS) -o $@ $(MINIZIP_DIR)/ioapi.so $(MINIZIP_DIR)/zip.so $^ -lz
|
||||
|
||||
# Targets for the object files.
|
||||
%.o : %.c $(HDRS)
|
||||
$(Q)$(CC) -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) -c $<
|
||||
|
||||
%.so : %.c $(HDRS)
|
||||
$(Q)$(CC) -fPIC -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
# Clean up any temp/build files.
|
||||
clean :
|
||||
$(Q)rm -f *.o *.a *.so *.dylib
|
422
src/app.c
Normal file
@ -0,0 +1,422 @@
|
||||
/*****************************************************************************
|
||||
* app - A library for creating Excel XLSX app files.
|
||||
*
|
||||
* Used in conjunction with the libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter/xmlwriter.h"
|
||||
#include "xlsxwriter/app.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
|
||||
#define APP_SCHEMA "http://schemas.openxmlformats.org/officeDocument/2006"
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Private functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Create a new app object.
|
||||
*/
|
||||
lxw_app *
|
||||
_new_app()
|
||||
{
|
||||
lxw_app *app = calloc(1, sizeof(lxw_app));
|
||||
GOTO_LABEL_ON_MEM_ERROR(app, mem_error);
|
||||
|
||||
app->heading_pairs = calloc(1, sizeof(struct lxw_heading_pairs));
|
||||
GOTO_LABEL_ON_MEM_ERROR(app->heading_pairs, mem_error);
|
||||
STAILQ_INIT(app->heading_pairs);
|
||||
|
||||
app->part_names = calloc(1, sizeof(struct lxw_part_names));
|
||||
GOTO_LABEL_ON_MEM_ERROR(app->part_names, mem_error);
|
||||
STAILQ_INIT(app->part_names);
|
||||
|
||||
return app;
|
||||
|
||||
mem_error:
|
||||
_free_app(app);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a app object.
|
||||
*/
|
||||
void
|
||||
_free_app(lxw_app *app)
|
||||
{
|
||||
lxw_heading_pair *heading_pair;
|
||||
lxw_part_name *part_name;
|
||||
|
||||
if (!app)
|
||||
return;
|
||||
|
||||
/* Free the lists in the App object. */
|
||||
while (!STAILQ_EMPTY(app->heading_pairs)) {
|
||||
heading_pair = STAILQ_FIRST(app->heading_pairs);
|
||||
STAILQ_REMOVE_HEAD(app->heading_pairs, list_pointers);
|
||||
free(heading_pair->key);
|
||||
free(heading_pair->value);
|
||||
free(heading_pair);
|
||||
}
|
||||
|
||||
while (!STAILQ_EMPTY(app->part_names)) {
|
||||
part_name = STAILQ_FIRST(app->part_names);
|
||||
STAILQ_REMOVE_HEAD(app->part_names, list_pointers);
|
||||
free(part_name->name);
|
||||
free(part_name);
|
||||
}
|
||||
|
||||
free(app->heading_pairs);
|
||||
free(app->part_names);
|
||||
free(app);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Write the XML declaration.
|
||||
*/
|
||||
STATIC void
|
||||
_app_xml_declaration(lxw_app *self)
|
||||
{
|
||||
_xml_declaration(self->file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <Properties> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_properties(lxw_app *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
char xmlns[] = APP_SCHEMA "/extended-properties";
|
||||
char xmlns_vt[] = APP_SCHEMA "/docPropsVTypes";
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
|
||||
_PUSH_ATTRIBUTES_STR("xmlns:vt", xmlns_vt);
|
||||
|
||||
_xml_start_tag(self->file, "Properties", &attributes);
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <Application> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_application(lxw_app *self)
|
||||
{
|
||||
_xml_data_element(self->file, "Application", "Microsoft Excel", NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <DocSecurity> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_doc_security(lxw_app *self)
|
||||
{
|
||||
_xml_data_element(self->file, "DocSecurity", "0", NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <ScaleCrop> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_scale_crop(lxw_app *self)
|
||||
{
|
||||
_xml_data_element(self->file, "ScaleCrop", "false", NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <vt:lpstr> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_vt_lpstr(lxw_app *self, const char *str)
|
||||
{
|
||||
_xml_data_element(self->file, "vt:lpstr", str, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <vt:i4> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_vt_i4(lxw_app *self, const char *value)
|
||||
{
|
||||
_xml_data_element(self->file, "vt:i4", value, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <vt:variant> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_vt_variant(lxw_app *self, const char *key, const char *value)
|
||||
{
|
||||
/* Write the vt:lpstr element. */
|
||||
_xml_start_tag(self->file, "vt:variant", NULL);
|
||||
_write_vt_lpstr(self, key);
|
||||
_xml_end_tag(self->file, "vt:variant");
|
||||
|
||||
/* Write the vt:i4 element. */
|
||||
_xml_start_tag(self->file, "vt:variant", NULL);
|
||||
_write_vt_i4(self, value);
|
||||
_xml_end_tag(self->file, "vt:variant");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <vt:vector> element for the heading pairs.
|
||||
*/
|
||||
STATIC void
|
||||
_write_vt_vector_heading_pairs(lxw_app *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
lxw_heading_pair *heading_pair;
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_INT("size", self->num_heading_pairs * 2);
|
||||
_PUSH_ATTRIBUTES_STR("baseType", "variant");
|
||||
|
||||
_xml_start_tag(self->file, "vt:vector", &attributes);
|
||||
|
||||
STAILQ_FOREACH(heading_pair, self->heading_pairs, list_pointers) {
|
||||
_write_vt_variant(self, heading_pair->key, heading_pair->value);
|
||||
}
|
||||
|
||||
_xml_end_tag(self->file, "vt:vector");
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <vt:vector> element for the named parts.
|
||||
*/
|
||||
STATIC void
|
||||
_write_vt_vector_lpstr_named_parts(lxw_app *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
lxw_part_name *part_name;
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_INT("size", self->num_part_names);
|
||||
_PUSH_ATTRIBUTES_STR("baseType", "lpstr");
|
||||
|
||||
_xml_start_tag(self->file, "vt:vector", &attributes);
|
||||
|
||||
STAILQ_FOREACH(part_name, self->part_names, list_pointers) {
|
||||
_write_vt_lpstr(self, part_name->name);
|
||||
}
|
||||
|
||||
_xml_end_tag(self->file, "vt:vector");
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <HeadingPairs> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_heading_pairs(lxw_app *self)
|
||||
{
|
||||
_xml_start_tag(self->file, "HeadingPairs", NULL);
|
||||
|
||||
/* Write the vt:vector element. */
|
||||
_write_vt_vector_heading_pairs(self);
|
||||
|
||||
_xml_end_tag(self->file, "HeadingPairs");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <TitlesOfParts> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_titles_of_parts(lxw_app *self)
|
||||
{
|
||||
_xml_start_tag(self->file, "TitlesOfParts", NULL);
|
||||
|
||||
/* Write the vt:vector element. */
|
||||
_write_vt_vector_lpstr_named_parts(self);
|
||||
|
||||
_xml_end_tag(self->file, "TitlesOfParts");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <Manager> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_manager(lxw_app *self)
|
||||
{
|
||||
lxw_doc_properties *properties = self->properties;
|
||||
|
||||
if (!properties)
|
||||
return;
|
||||
|
||||
if (properties->manager)
|
||||
_xml_data_element(self->file, "Manager", properties->manager, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <Company> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_company(lxw_app *self)
|
||||
{
|
||||
lxw_doc_properties *properties = self->properties;
|
||||
|
||||
if (properties && properties->company)
|
||||
_xml_data_element(self->file, "Company", properties->company, NULL);
|
||||
else
|
||||
_xml_data_element(self->file, "Company", "", NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <LinksUpToDate> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_links_up_to_date(lxw_app *self)
|
||||
{
|
||||
_xml_data_element(self->file, "LinksUpToDate", "false", NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <SharedDoc> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_shared_doc(lxw_app *self)
|
||||
{
|
||||
_xml_data_element(self->file, "SharedDoc", "false", NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <HyperlinksChanged> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_hyperlinks_changed(lxw_app *self)
|
||||
{
|
||||
_xml_data_element(self->file, "HyperlinksChanged", "false", NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <AppVersion> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_app_version(lxw_app *self)
|
||||
{
|
||||
_xml_data_element(self->file, "AppVersion", "12.0000", NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML file assembly functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Assemble and write the XML file.
|
||||
*/
|
||||
void
|
||||
_app_assemble_xml_file(lxw_app *self)
|
||||
{
|
||||
|
||||
/* Write the XML declaration. */
|
||||
_app_xml_declaration(self);
|
||||
|
||||
_write_properties(self);
|
||||
_write_application(self);
|
||||
_write_doc_security(self);
|
||||
_write_scale_crop(self);
|
||||
_write_heading_pairs(self);
|
||||
_write_titles_of_parts(self);
|
||||
_write_manager(self);
|
||||
_write_company(self);
|
||||
_write_links_up_to_date(self);
|
||||
_write_shared_doc(self);
|
||||
_write_hyperlinks_changed(self);
|
||||
_write_app_version(self);
|
||||
|
||||
_xml_end_tag(self->file, "Properties");
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Public functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Add the name of a workbook Part such as 'Sheet1' or 'Print_Titles'.
|
||||
*/
|
||||
void
|
||||
_add_part_name(lxw_app *self, const char *name)
|
||||
{
|
||||
lxw_part_name *part_name;
|
||||
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
part_name = calloc(1, sizeof(lxw_part_name));
|
||||
GOTO_LABEL_ON_MEM_ERROR(part_name, mem_error);
|
||||
|
||||
part_name->name = __builtin_strdup(name);
|
||||
GOTO_LABEL_ON_MEM_ERROR(part_name->name, mem_error);
|
||||
|
||||
STAILQ_INSERT_TAIL(self->part_names, part_name, list_pointers);
|
||||
self->num_part_names++;
|
||||
|
||||
return;
|
||||
|
||||
mem_error:
|
||||
if (part_name) {
|
||||
free(part_name->name);
|
||||
free(part_name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the name of a workbook Heading Pair such as 'Worksheets', 'Charts' or
|
||||
* 'Named Ranges'.
|
||||
*/
|
||||
void
|
||||
_add_heading_pair(lxw_app *self, const char *key, const char *value)
|
||||
{
|
||||
lxw_heading_pair *heading_pair;
|
||||
|
||||
if (!key || !value)
|
||||
return;
|
||||
|
||||
heading_pair = calloc(1, sizeof(lxw_heading_pair));
|
||||
GOTO_LABEL_ON_MEM_ERROR(heading_pair, mem_error);
|
||||
|
||||
heading_pair->key = __builtin_strdup(key);
|
||||
GOTO_LABEL_ON_MEM_ERROR(heading_pair->key, mem_error);
|
||||
|
||||
heading_pair->value = __builtin_strdup(value);
|
||||
GOTO_LABEL_ON_MEM_ERROR(heading_pair->value, mem_error);
|
||||
|
||||
STAILQ_INSERT_TAIL(self->heading_pairs, heading_pair, list_pointers);
|
||||
self->num_heading_pairs++;
|
||||
|
||||
return;
|
||||
|
||||
mem_error:
|
||||
if (heading_pair) {
|
||||
free(heading_pair->key);
|
||||
free(heading_pair->value);
|
||||
free(heading_pair);
|
||||
}
|
||||
}
|
315
src/content_types.c
Normal file
@ -0,0 +1,315 @@
|
||||
/*****************************************************************************
|
||||
* content_types - A library for creating Excel XLSX content_types files.
|
||||
*
|
||||
* Used in conjunction with the libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter/xmlwriter.h"
|
||||
#include "xlsxwriter/content_types.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Private functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Create a new content_types object.
|
||||
*/
|
||||
lxw_content_types *
|
||||
_new_content_types()
|
||||
{
|
||||
lxw_content_types *content_types = calloc(1, sizeof(lxw_content_types));
|
||||
GOTO_LABEL_ON_MEM_ERROR(content_types, mem_error);
|
||||
|
||||
content_types->default_types = calloc(1, sizeof(struct lxw_tuples));
|
||||
GOTO_LABEL_ON_MEM_ERROR(content_types->default_types, mem_error);
|
||||
STAILQ_INIT(content_types->default_types);
|
||||
|
||||
content_types->overrides = calloc(1, sizeof(struct lxw_tuples));
|
||||
GOTO_LABEL_ON_MEM_ERROR(content_types->overrides, mem_error);
|
||||
STAILQ_INIT(content_types->overrides);
|
||||
|
||||
_ct_add_default(content_types, "rels",
|
||||
LXW_APP_PACKAGE "relationships+xml");
|
||||
_ct_add_default(content_types, "xml", "application/xml");
|
||||
|
||||
_ct_add_override(content_types, "/docProps/app.xml",
|
||||
LXW_APP_DOCUMENT "extended-properties+xml");
|
||||
_ct_add_override(content_types, "/docProps/core.xml",
|
||||
LXW_APP_PACKAGE "core-properties+xml");
|
||||
_ct_add_override(content_types, "/xl/styles.xml",
|
||||
LXW_APP_DOCUMENT "spreadsheetml.styles+xml");
|
||||
_ct_add_override(content_types, "/xl/theme/theme1.xml",
|
||||
LXW_APP_DOCUMENT "theme+xml");
|
||||
_ct_add_override(content_types, "/xl/workbook.xml",
|
||||
LXW_APP_DOCUMENT "spreadsheetml.sheet.main+xml");
|
||||
|
||||
return content_types;
|
||||
|
||||
mem_error:
|
||||
_free_content_types(content_types);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a content_types object.
|
||||
*/
|
||||
void
|
||||
_free_content_types(lxw_content_types *content_types)
|
||||
{
|
||||
lxw_tuple *default_type;
|
||||
lxw_tuple *override;
|
||||
|
||||
if (!content_types)
|
||||
return;
|
||||
|
||||
while (!STAILQ_EMPTY(content_types->default_types)) {
|
||||
default_type = STAILQ_FIRST(content_types->default_types);
|
||||
STAILQ_REMOVE_HEAD(content_types->default_types, list_pointers);
|
||||
free(default_type->key);
|
||||
free(default_type->value);
|
||||
free(default_type);
|
||||
}
|
||||
|
||||
while (!STAILQ_EMPTY(content_types->overrides)) {
|
||||
override = STAILQ_FIRST(content_types->overrides);
|
||||
STAILQ_REMOVE_HEAD(content_types->overrides, list_pointers);
|
||||
free(override->key);
|
||||
free(override->value);
|
||||
free(override);
|
||||
}
|
||||
|
||||
free(content_types->default_types);
|
||||
free(content_types->overrides);
|
||||
free(content_types);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Write the XML declaration.
|
||||
*/
|
||||
STATIC void
|
||||
_content_types_xml_declaration(lxw_content_types *self)
|
||||
{
|
||||
_xml_declaration(self->file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <Types> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_types(lxw_content_types *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_STR("xmlns", LXW_CONTENT_TYPE_SCHEMA);
|
||||
|
||||
_xml_start_tag(self->file, "Types", &attributes);
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <Default> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_default(lxw_content_types *self, const char *ext, const char *type)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_STR("Extension", ext);
|
||||
_PUSH_ATTRIBUTES_STR("ContentType", type);
|
||||
|
||||
_xml_empty_tag(self->file, "Default", &attributes);
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <Override> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_override(lxw_content_types *self, const char *part_name,
|
||||
const char *type)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_STR("PartName", part_name);
|
||||
_PUSH_ATTRIBUTES_STR("ContentType", type);
|
||||
|
||||
_xml_empty_tag(self->file, "Override", &attributes);
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML file assembly functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Write out all of the <Default> types.
|
||||
*/
|
||||
STATIC void
|
||||
_write_defaults(lxw_content_types *self)
|
||||
{
|
||||
lxw_tuple *tuple;
|
||||
|
||||
STAILQ_FOREACH(tuple, self->default_types, list_pointers) {
|
||||
_write_default(self, tuple->key, tuple->value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out all of the <Override> types.
|
||||
*/
|
||||
STATIC void
|
||||
_write_overrides(lxw_content_types *self)
|
||||
{
|
||||
lxw_tuple *tuple;
|
||||
|
||||
STAILQ_FOREACH(tuple, self->overrides, list_pointers) {
|
||||
_write_override(self, tuple->key, tuple->value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Assemble and write the XML file.
|
||||
*/
|
||||
void
|
||||
_content_types_assemble_xml_file(lxw_content_types *self)
|
||||
{
|
||||
/* Write the XML declaration. */
|
||||
_content_types_xml_declaration(self);
|
||||
|
||||
_write_types(self);
|
||||
_write_defaults(self);
|
||||
_write_overrides(self);
|
||||
|
||||
/* Close the content_types tag. */
|
||||
_xml_end_tag(self->file, "Types");
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Public functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
/*
|
||||
* Add elements to the ContentTypes defaults.
|
||||
*/
|
||||
void
|
||||
_ct_add_default(lxw_content_types *self, const char *key, const char *value)
|
||||
{
|
||||
lxw_tuple *tuple;
|
||||
|
||||
if (!key || !value)
|
||||
return;
|
||||
|
||||
tuple = calloc(1, sizeof(lxw_tuple));
|
||||
GOTO_LABEL_ON_MEM_ERROR(tuple, mem_error);
|
||||
|
||||
tuple->key = __builtin_strdup(key);
|
||||
GOTO_LABEL_ON_MEM_ERROR(tuple->key, mem_error);
|
||||
|
||||
tuple->value = __builtin_strdup(value);
|
||||
GOTO_LABEL_ON_MEM_ERROR(tuple->value, mem_error);
|
||||
|
||||
STAILQ_INSERT_TAIL(self->default_types, tuple, list_pointers);
|
||||
|
||||
return;
|
||||
|
||||
mem_error:
|
||||
if (tuple) {
|
||||
free(tuple->key);
|
||||
free(tuple->value);
|
||||
free(tuple);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add elements to the ContentTypes overrides.
|
||||
*/
|
||||
void
|
||||
_ct_add_override(lxw_content_types *self, const char *key, const char *value)
|
||||
{
|
||||
lxw_tuple *tuple;
|
||||
|
||||
if (!key || !value)
|
||||
return;
|
||||
|
||||
tuple = calloc(1, sizeof(lxw_tuple));
|
||||
GOTO_LABEL_ON_MEM_ERROR(tuple, mem_error);
|
||||
|
||||
tuple->key = __builtin_strdup(key);
|
||||
GOTO_LABEL_ON_MEM_ERROR(tuple->key, mem_error);
|
||||
|
||||
tuple->value = __builtin_strdup(value);
|
||||
GOTO_LABEL_ON_MEM_ERROR(tuple->value, mem_error);
|
||||
|
||||
STAILQ_INSERT_TAIL(self->overrides, tuple, list_pointers);
|
||||
|
||||
return;
|
||||
|
||||
mem_error:
|
||||
if (tuple) {
|
||||
free(tuple->key);
|
||||
free(tuple->value);
|
||||
free(tuple);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the name of a worksheet to the ContentTypes overrides.
|
||||
*/
|
||||
void
|
||||
_ct_add_worksheet_name(lxw_content_types *self, const char *str)
|
||||
{
|
||||
char name[MAX_ATTRIBUTE_LENGTH];
|
||||
__builtin_snprintf(name, MAX_ATTRIBUTE_LENGTH, "/xl/worksheets/%s.xml",
|
||||
str);
|
||||
|
||||
_ct_add_override(self, name,
|
||||
LXW_APP_DOCUMENT "spreadsheetml.worksheet+xml");
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the sharedStrings link to the ContentTypes overrides.
|
||||
*/
|
||||
void
|
||||
_ct_add_shared_strings(lxw_content_types *self)
|
||||
{
|
||||
_ct_add_override(self, "/xl/sharedStrings.xml",
|
||||
LXW_APP_DOCUMENT "spreadsheetml.sharedStrings+xml");
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the calcChain link to the ContentTypes overrides.
|
||||
*/
|
||||
void
|
||||
_ct_add_calc_chain(lxw_content_types *self)
|
||||
{
|
||||
_ct_add_override(self, "/xl/calcChain.xml",
|
||||
LXW_APP_DOCUMENT "spreadsheetml.calcChain+xml");
|
||||
}
|
290
src/core.c
Normal file
@ -0,0 +1,290 @@
|
||||
/*****************************************************************************
|
||||
* core - A library for creating Excel XLSX core files.
|
||||
*
|
||||
* Used in conjunction with the libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter/xmlwriter.h"
|
||||
#include "xlsxwriter/core.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Private functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Create a new core object.
|
||||
*/
|
||||
lxw_core *
|
||||
_new_core()
|
||||
{
|
||||
lxw_core *core = calloc(1, sizeof(lxw_core));
|
||||
GOTO_LABEL_ON_MEM_ERROR(core, mem_error);
|
||||
|
||||
return core;
|
||||
|
||||
mem_error:
|
||||
_free_core(core);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a core object.
|
||||
*/
|
||||
void
|
||||
_free_core(lxw_core *core)
|
||||
{
|
||||
if (!core)
|
||||
return;
|
||||
|
||||
free(core);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a time_t struct to a ISO 8601 style "2010-01-01T00:00:00Z" date.
|
||||
*/
|
||||
static void
|
||||
_localtime_to_iso8601_date(time_t *timer, char *str, size_t size)
|
||||
{
|
||||
struct tm *tmp_localtime;
|
||||
time_t current_time = time(NULL);
|
||||
|
||||
if (*timer)
|
||||
tmp_localtime = localtime(timer);
|
||||
else
|
||||
tmp_localtime = localtime(¤t_time);
|
||||
|
||||
strftime(str, size - 1, "%Y-%m-%dT%H:%M:%SZ", tmp_localtime);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Write the XML declaration.
|
||||
*/
|
||||
STATIC void
|
||||
_core_xml_declaration(lxw_core *self)
|
||||
{
|
||||
_xml_declaration(self->file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <cp:coreProperties> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_cp_core_properties(lxw_core *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_STR("xmlns:cp",
|
||||
"http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
|
||||
_PUSH_ATTRIBUTES_STR("xmlns:dc", "http://purl.org/dc/elements/1.1/");
|
||||
_PUSH_ATTRIBUTES_STR("xmlns:dcterms", "http://purl.org/dc/terms/");
|
||||
_PUSH_ATTRIBUTES_STR("xmlns:dcmitype", "http://purl.org/dc/dcmitype/");
|
||||
_PUSH_ATTRIBUTES_STR("xmlns:xsi",
|
||||
"http://www.w3.org/2001/XMLSchema-instance");
|
||||
|
||||
_xml_start_tag(self->file, "cp:coreProperties", &attributes);
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <dc:creator> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_dc_creator(lxw_core *self)
|
||||
{
|
||||
if (self->properties->author) {
|
||||
_xml_data_element(self->file, "dc:creator", self->properties->author,
|
||||
NULL);
|
||||
}
|
||||
else {
|
||||
_xml_data_element(self->file, "dc:creator", "", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <cp:lastModifiedBy> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_cp_last_modified_by(lxw_core *self)
|
||||
{
|
||||
if (self->properties->author) {
|
||||
_xml_data_element(self->file, "cp:lastModifiedBy",
|
||||
self->properties->author, NULL);
|
||||
}
|
||||
else {
|
||||
_xml_data_element(self->file, "cp:lastModifiedBy", "", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <dcterms:created> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_dcterms_created(lxw_core *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
char datetime[ATTR_32];
|
||||
|
||||
_localtime_to_iso8601_date(&self->properties->created, datetime,
|
||||
MAX_ATTRIBUTE_LENGTH);
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_STR("xsi:type", "dcterms:W3CDTF");
|
||||
|
||||
_xml_data_element(self->file, "dcterms:created", datetime, &attributes);
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <dcterms:modified> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_dcterms_modified(lxw_core *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
char datetime[ATTR_32];
|
||||
|
||||
_localtime_to_iso8601_date(&self->properties->created, datetime,
|
||||
MAX_ATTRIBUTE_LENGTH);
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_STR("xsi:type", "dcterms:W3CDTF");
|
||||
|
||||
_xml_data_element(self->file, "dcterms:modified", datetime, &attributes);
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <dc:title> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_dc_title(lxw_core *self)
|
||||
{
|
||||
if (!self->properties->title)
|
||||
return;
|
||||
|
||||
_xml_data_element(self->file, "dc:title", self->properties->title, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <dc:subject> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_dc_subject(lxw_core *self)
|
||||
{
|
||||
if (!self->properties->subject)
|
||||
return;
|
||||
|
||||
_xml_data_element(self->file, "dc:subject", self->properties->subject,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <cp:keywords> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_cp_keywords(lxw_core *self)
|
||||
{
|
||||
if (!self->properties->keywords)
|
||||
return;
|
||||
|
||||
_xml_data_element(self->file, "cp:keywords", self->properties->keywords,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <dc:description> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_dc_description(lxw_core *self)
|
||||
{
|
||||
if (!self->properties->comments)
|
||||
return;
|
||||
|
||||
_xml_data_element(self->file, "dc:description",
|
||||
self->properties->comments, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <cp:category> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_cp_category(lxw_core *self)
|
||||
{
|
||||
if (!self->properties->category)
|
||||
return;
|
||||
|
||||
_xml_data_element(self->file, "cp:category", self->properties->category,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <cp:contentStatus> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_cp_content_status(lxw_core *self)
|
||||
{
|
||||
if (!self->properties->status)
|
||||
return;
|
||||
|
||||
_xml_data_element(self->file, "cp:contentStatus",
|
||||
self->properties->status, NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML file assembly functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Assemble and write the XML file.
|
||||
*/
|
||||
void
|
||||
_core_assemble_xml_file(lxw_core *self)
|
||||
{
|
||||
/* Write the XML declaration. */
|
||||
_core_xml_declaration(self);
|
||||
|
||||
_write_cp_core_properties(self);
|
||||
_write_dc_title(self);
|
||||
_write_dc_subject(self);
|
||||
_write_dc_creator(self);
|
||||
_write_cp_keywords(self);
|
||||
_write_dc_description(self);
|
||||
_write_cp_last_modified_by(self);
|
||||
_write_dcterms_created(self);
|
||||
_write_dcterms_modified(self);
|
||||
_write_cp_category(self);
|
||||
_write_cp_content_status(self);
|
||||
|
||||
_xml_end_tag(self->file, "cp:coreProperties");
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Public functions.
|
||||
*
|
||||
****************************************************************************/
|
728
src/format.c
Normal file
@ -0,0 +1,728 @@
|
||||
/*****************************************************************************
|
||||
* format - A library for creating Excel XLSX format files.
|
||||
*
|
||||
* Used in conjunction with the libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter/xmlwriter.h"
|
||||
#include "xlsxwriter/format.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Private functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Create a new format object.
|
||||
*/
|
||||
lxw_format *
|
||||
_new_format()
|
||||
{
|
||||
lxw_format *format = calloc(1, sizeof(lxw_format));
|
||||
GOTO_LABEL_ON_MEM_ERROR(format, mem_error);
|
||||
|
||||
format->xf_format_indices = NULL;
|
||||
|
||||
format->xf_index = LXW_PROPERTY_UNSET;
|
||||
format->dxf_index = LXW_PROPERTY_UNSET;
|
||||
|
||||
format->font_name[0] = '\0';
|
||||
format->font_scheme[0] = '\0';
|
||||
format->num_format[0] = '\0';
|
||||
format->num_format_index = 0;
|
||||
format->font_index = 0;
|
||||
format->has_font = LXW_FALSE;
|
||||
format->has_dxf_font = LXW_FALSE;
|
||||
format->font_size = 11;
|
||||
format->bold = LXW_FALSE;
|
||||
format->italic = LXW_FALSE;
|
||||
format->font_color = LXW_COLOR_UNSET;
|
||||
format->underline = LXW_FALSE;
|
||||
format->font_strikeout = LXW_FALSE;
|
||||
format->font_outline = LXW_FALSE;
|
||||
format->font_shadow = LXW_FALSE;
|
||||
format->font_script = LXW_FALSE;
|
||||
format->font_family = LXW_DEFAULT_FONT_FAMILY;
|
||||
format->font_charset = LXW_FALSE;
|
||||
format->font_condense = LXW_FALSE;
|
||||
format->font_extend = LXW_FALSE;
|
||||
format->theme = LXW_FALSE;
|
||||
format->hyperlink = LXW_FALSE;
|
||||
|
||||
format->hidden = LXW_FALSE;
|
||||
format->locked = LXW_TRUE;
|
||||
|
||||
format->text_h_align = LXW_ALIGN_NONE;
|
||||
format->text_wrap = LXW_FALSE;
|
||||
format->text_v_align = LXW_ALIGN_NONE;
|
||||
format->text_justlast = LXW_FALSE;
|
||||
format->rotation = 0;
|
||||
|
||||
format->fg_color = LXW_COLOR_UNSET;
|
||||
format->bg_color = LXW_COLOR_UNSET;
|
||||
format->pattern = LXW_PATTERN_NONE;
|
||||
format->has_fill = LXW_FALSE;
|
||||
format->has_dxf_fill = LXW_FALSE;
|
||||
format->fill_index = 0;
|
||||
format->fill_count = 0;
|
||||
|
||||
format->border_index = 0;
|
||||
format->has_border = LXW_FALSE;
|
||||
format->has_dxf_border = LXW_FALSE;
|
||||
format->border_count = 0;
|
||||
|
||||
format->bottom = LXW_BORDER_NONE;
|
||||
format->left = LXW_BORDER_NONE;
|
||||
format->right = LXW_BORDER_NONE;
|
||||
format->top = LXW_BORDER_NONE;
|
||||
format->diag_border = LXW_BORDER_NONE;
|
||||
format->diag_type = LXW_BORDER_NONE;
|
||||
format->bottom_color = LXW_COLOR_UNSET;
|
||||
format->left_color = LXW_COLOR_UNSET;
|
||||
format->right_color = LXW_COLOR_UNSET;
|
||||
format->top_color = LXW_COLOR_UNSET;
|
||||
format->diag_color = LXW_COLOR_UNSET;
|
||||
|
||||
format->indent = 0;
|
||||
format->shrink = LXW_FALSE;
|
||||
format->merge_range = LXW_FALSE;
|
||||
format->reading_order = 0;
|
||||
format->just_distrib = LXW_FALSE;
|
||||
format->color_indexed = LXW_FALSE;
|
||||
format->font_only = LXW_FALSE;
|
||||
|
||||
return format;
|
||||
|
||||
mem_error:
|
||||
_free_format(format);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a format object.
|
||||
*/
|
||||
void
|
||||
_free_format(lxw_format *format)
|
||||
{
|
||||
if (!format)
|
||||
return;
|
||||
|
||||
free(format);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a user input color.
|
||||
*/
|
||||
lxw_color_t
|
||||
_check_color(lxw_color_t color)
|
||||
{
|
||||
if (color == LXW_COLOR_UNSET)
|
||||
return color;
|
||||
else
|
||||
return color & LXW_COLOR_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a user input border.
|
||||
*/
|
||||
uint8_t
|
||||
_check_border(uint8_t border)
|
||||
{
|
||||
if (border >= LXW_BORDER_THIN && border <= LXW_BORDER_SLANT_DASH_DOT)
|
||||
return border;
|
||||
else
|
||||
return LXW_BORDER_NONE;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Public functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Returns a format struct suitable for hashing as a lookup key. This is
|
||||
* mainly a memcpy with any pointer members set to NULL.
|
||||
*/
|
||||
lxw_format *
|
||||
_get_format_key(lxw_format *self)
|
||||
{
|
||||
lxw_format *key = calloc(1, sizeof(lxw_format));
|
||||
GOTO_LABEL_ON_MEM_ERROR(key, mem_error);
|
||||
|
||||
memcpy(key, self, sizeof(lxw_format));
|
||||
|
||||
/* Set pointer members to NULL since they aren't part of the comparison. */
|
||||
key->xf_format_indices = NULL;
|
||||
key->num_xf_formats = NULL;
|
||||
key->list_pointers.stqe_next = NULL;
|
||||
|
||||
return key;
|
||||
|
||||
mem_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a font struct suitable for hashing as a lookup key.
|
||||
*/
|
||||
lxw_font *
|
||||
_get_font_key(lxw_format *self)
|
||||
{
|
||||
lxw_font *key = calloc(1, sizeof(lxw_font));
|
||||
GOTO_LABEL_ON_MEM_ERROR(key, mem_error);
|
||||
|
||||
LXW_FORMAT_FIELD_COPY(key->font_name, self->font_name);
|
||||
key->font_size = self->font_size;
|
||||
key->bold = self->bold;
|
||||
key->italic = self->italic;
|
||||
key->font_color = self->font_color;
|
||||
key->underline = self->underline;
|
||||
key->font_strikeout = self->font_strikeout;
|
||||
key->font_outline = self->font_outline;
|
||||
key->font_shadow = self->font_shadow;
|
||||
key->font_script = self->font_script;
|
||||
key->font_family = self->font_family;
|
||||
key->font_charset = self->font_charset;
|
||||
key->font_condense = self->font_condense;
|
||||
key->font_extend = self->font_extend;
|
||||
|
||||
return key;
|
||||
|
||||
mem_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a border struct suitable for hashing as a lookup key.
|
||||
*/
|
||||
lxw_border *
|
||||
_get_border_key(lxw_format *self)
|
||||
{
|
||||
lxw_border *key = calloc(1, sizeof(lxw_border));
|
||||
GOTO_LABEL_ON_MEM_ERROR(key, mem_error);
|
||||
|
||||
key->bottom = self->bottom;
|
||||
key->left = self->left;
|
||||
key->right = self->right;
|
||||
key->top = self->top;
|
||||
key->diag_border = self->diag_border;
|
||||
key->diag_type = self->diag_type;
|
||||
key->bottom_color = self->bottom_color;
|
||||
key->left_color = self->left_color;
|
||||
key->right_color = self->right_color;
|
||||
key->top_color = self->top_color;
|
||||
key->diag_color = self->diag_color;
|
||||
|
||||
return key;
|
||||
|
||||
mem_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a pattern fill struct suitable for hashing as a lookup key.
|
||||
*/
|
||||
lxw_fill *
|
||||
_get_fill_key(lxw_format *self)
|
||||
{
|
||||
lxw_fill *key = calloc(1, sizeof(lxw_fill));
|
||||
GOTO_LABEL_ON_MEM_ERROR(key, mem_error);
|
||||
|
||||
key->fg_color = self->fg_color;
|
||||
key->bg_color = self->bg_color;
|
||||
key->pattern = self->pattern;
|
||||
|
||||
return key;
|
||||
|
||||
mem_error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the XF index number used by Excel to identify a format.
|
||||
*/
|
||||
int32_t
|
||||
_get_xf_index(lxw_format *self)
|
||||
{
|
||||
lxw_format *format_key;
|
||||
lxw_format *existing_format;
|
||||
lxw_hash_element *hash_element;
|
||||
lxw_hash_table *formats_hash_table = self->xf_format_indices;
|
||||
int32_t index;
|
||||
|
||||
/* Note: The formats_hash_table/xf_format_indices contains the unique and
|
||||
* more importantly the *used* formats in the workbook.
|
||||
*/
|
||||
|
||||
/* Format already has an index number so return it. */
|
||||
if (self->xf_index != LXW_PROPERTY_UNSET) {
|
||||
return self->xf_index;
|
||||
}
|
||||
|
||||
/* Otherwise, the format doesn't have an index number so we assign one.
|
||||
* First generate a unique key to identify the format in the hash table.
|
||||
*/
|
||||
format_key = _get_format_key(self);
|
||||
|
||||
/* Return the default format index if the key generation failed. */
|
||||
if (!format_key)
|
||||
return 0;
|
||||
|
||||
/* Look up the format in the hash table. */
|
||||
hash_element =
|
||||
_hash_key_exists(formats_hash_table, format_key, sizeof(lxw_format));
|
||||
|
||||
if (hash_element) {
|
||||
/* Format matches existing format with an index. */
|
||||
free(format_key);
|
||||
existing_format = hash_element->value;
|
||||
return existing_format->xf_index;
|
||||
}
|
||||
else {
|
||||
/* New format requiring an index. Note. +1 since Excel has an
|
||||
* implicit "General" format at index 0.
|
||||
*/
|
||||
index = formats_hash_table->unique_count;
|
||||
self->xf_index = index;
|
||||
_insert_hash_element(formats_hash_table, format_key, self,
|
||||
sizeof(lxw_format));
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_name property.
|
||||
*/
|
||||
void
|
||||
format_set_font_name(lxw_format *self, const char *font_name)
|
||||
{
|
||||
LXW_FORMAT_FIELD_COPY(self->font_name, font_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_size property.
|
||||
*/
|
||||
void
|
||||
format_set_font_size(lxw_format *self, uint16_t size)
|
||||
{
|
||||
|
||||
if (size >= LXW_MIN_FONT_SIZE && size <= LXW_MAX_FONT_SIZE)
|
||||
self->font_size = size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_color property.
|
||||
*/
|
||||
void
|
||||
format_set_font_color(lxw_format *self, lxw_color_t color)
|
||||
{
|
||||
self->font_color = _check_color(color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the bold property.
|
||||
*/
|
||||
void
|
||||
format_set_bold(lxw_format *self)
|
||||
{
|
||||
self->bold = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the italic property.
|
||||
*/
|
||||
|
||||
void
|
||||
format_set_italic(lxw_format *self)
|
||||
{
|
||||
self->italic = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the underline property.
|
||||
*/
|
||||
void
|
||||
format_set_underline(lxw_format *self, uint8_t style)
|
||||
{
|
||||
if (style >= LXW_UNDERLINE_SINGLE
|
||||
&& style <= LXW_UNDERLINE_DOUBLE_ACCOUNTING)
|
||||
self->underline = style;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_strikeout property.
|
||||
*/
|
||||
void
|
||||
format_set_font_strikeout(lxw_format *self)
|
||||
{
|
||||
self->font_strikeout = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_script property.
|
||||
*/
|
||||
void
|
||||
format_set_font_script(lxw_format *self, uint8_t style)
|
||||
{
|
||||
if (style >= LXW_FONT_SUPERSCRIPT && style <= LXW_FONT_SUBSCRIPT)
|
||||
self->font_script = style;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_outline property.
|
||||
*/
|
||||
void
|
||||
format_set_font_outline(lxw_format *self)
|
||||
{
|
||||
self->font_outline = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_shadow property.
|
||||
*/
|
||||
void
|
||||
format_set_font_shadow(lxw_format *self)
|
||||
{
|
||||
self->font_shadow = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the num_format property.
|
||||
*/
|
||||
void
|
||||
format_set_num_format(lxw_format *self, const char *num_format)
|
||||
{
|
||||
LXW_FORMAT_FIELD_COPY(self->num_format, num_format);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the unlocked property.
|
||||
*/
|
||||
void
|
||||
format_set_unlocked(lxw_format *self)
|
||||
{
|
||||
self->locked = LXW_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the hidden property.
|
||||
*/
|
||||
void
|
||||
format_set_hidden(lxw_format *self)
|
||||
{
|
||||
self->hidden = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the align property.
|
||||
*/
|
||||
void
|
||||
format_set_align(lxw_format *self, uint8_t value)
|
||||
{
|
||||
if (value >= LXW_ALIGN_LEFT && value <= LXW_ALIGN_DISTRIBUTED) {
|
||||
self->text_h_align = value;
|
||||
}
|
||||
|
||||
if (value >= LXW_ALIGN_VERTICAL_TOP
|
||||
&& value <= LXW_ALIGN_VERTICAL_DISTRIBUTED) {
|
||||
self->text_v_align = value;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the text_wrap property.
|
||||
*/
|
||||
void
|
||||
format_set_text_wrap(lxw_format *self)
|
||||
{
|
||||
self->text_wrap = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the rotation property.
|
||||
*/
|
||||
void
|
||||
format_set_rotation(lxw_format *self, int16_t angle)
|
||||
{
|
||||
/* Convert user angle to Excel angle. */
|
||||
if (angle == 270) {
|
||||
self->rotation = 255;
|
||||
}
|
||||
else if (angle >= -90 || angle <= 90) {
|
||||
if (angle < 0)
|
||||
angle = -angle + 90;
|
||||
|
||||
self->rotation = angle;
|
||||
}
|
||||
else {
|
||||
LXW_WARN("Rotation rotation outside range: -90 <= angle <= 90");
|
||||
self->rotation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the indent property.
|
||||
*/
|
||||
void
|
||||
format_set_indent(lxw_format *self, uint8_t value)
|
||||
{
|
||||
self->indent = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the shrink property.
|
||||
*/
|
||||
void
|
||||
format_set_shrink(lxw_format *self)
|
||||
{
|
||||
self->shrink = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the text_justlast property.
|
||||
*/
|
||||
void
|
||||
format_set_text_justlast(lxw_format *self)
|
||||
{
|
||||
self->text_justlast = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the pattern property.
|
||||
*/
|
||||
void
|
||||
format_set_pattern(lxw_format *self, uint8_t value)
|
||||
{
|
||||
self->pattern = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the bg_color property.
|
||||
*/
|
||||
void
|
||||
format_set_bg_color(lxw_format *self, lxw_color_t color)
|
||||
{
|
||||
self->bg_color = _check_color(color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the fg_color property.
|
||||
*/
|
||||
void
|
||||
format_set_fg_color(lxw_format *self, lxw_color_t color)
|
||||
{
|
||||
self->fg_color = _check_color(color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the border property.
|
||||
*/
|
||||
void
|
||||
format_set_border(lxw_format *self, uint8_t style)
|
||||
{
|
||||
style = _check_border(style);
|
||||
self->bottom = style;
|
||||
self->top = style;
|
||||
self->left = style;
|
||||
self->right = style;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the border_color property.
|
||||
*/
|
||||
void
|
||||
format_set_border_color(lxw_format *self, lxw_color_t color)
|
||||
{
|
||||
color = _check_color(color);
|
||||
self->bottom_color = color;
|
||||
self->top_color = color;
|
||||
self->left_color = color;
|
||||
self->right_color = color;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the bottom property.
|
||||
*/
|
||||
void
|
||||
format_set_bottom(lxw_format *self, uint8_t style)
|
||||
{
|
||||
self->bottom = _check_border(style);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the bottom_color property.
|
||||
*/
|
||||
void
|
||||
format_set_bottom_color(lxw_format *self, lxw_color_t color)
|
||||
{
|
||||
self->bottom_color = _check_color(color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the left property.
|
||||
*/
|
||||
void
|
||||
format_set_left(lxw_format *self, uint8_t style)
|
||||
{
|
||||
self->left = _check_border(style);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the left_color property.
|
||||
*/
|
||||
void
|
||||
format_set_left_color(lxw_format *self, lxw_color_t color)
|
||||
{
|
||||
self->left_color = _check_color(color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the right property.
|
||||
*/
|
||||
void
|
||||
format_set_right(lxw_format *self, uint8_t style)
|
||||
{
|
||||
self->right = _check_border(style);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the right_color property.
|
||||
*/
|
||||
void
|
||||
format_set_right_color(lxw_format *self, lxw_color_t color)
|
||||
{
|
||||
self->right_color = _check_color(color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the top property.
|
||||
*/
|
||||
void
|
||||
format_set_top(lxw_format *self, uint8_t style)
|
||||
{
|
||||
self->top = _check_border(style);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the top_color property.
|
||||
*/
|
||||
void
|
||||
format_set_top_color(lxw_format *self, lxw_color_t color)
|
||||
{
|
||||
self->top_color = _check_color(color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the diag_type property.
|
||||
*/
|
||||
void
|
||||
format_set_diag_type(lxw_format *self, uint8_t type)
|
||||
{
|
||||
if (type >= LXW_DIAGONAL_BORDER_UP && type <= LXW_DIAGONAL_BORDER_UP_DOWN)
|
||||
self->diag_type = type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the diag_color property.
|
||||
*/
|
||||
void
|
||||
format_set_diag_color(lxw_format *self, lxw_color_t color)
|
||||
{
|
||||
self->diag_color = _check_color(color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the diag_border property.
|
||||
*/
|
||||
void
|
||||
format_set_diag_border(lxw_format *self, uint8_t style)
|
||||
{
|
||||
self->diag_border = style;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the num_format_index property.
|
||||
*/
|
||||
void
|
||||
format_set_num_format_index(lxw_format *self, uint8_t value)
|
||||
{
|
||||
self->num_format_index = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the valign property.
|
||||
*/
|
||||
void
|
||||
format_set_valign(lxw_format *self, uint8_t value)
|
||||
{
|
||||
self->text_v_align = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the reading_order property.
|
||||
*/
|
||||
void
|
||||
format_set_reading_order(lxw_format *self, uint8_t value)
|
||||
{
|
||||
self->reading_order = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_family property.
|
||||
*/
|
||||
void
|
||||
format_set_font_family(lxw_format *self, uint8_t value)
|
||||
{
|
||||
self->font_family = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_charset property.
|
||||
*/
|
||||
void
|
||||
format_set_font_charset(lxw_format *self, uint8_t value)
|
||||
{
|
||||
self->font_charset = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_scheme property.
|
||||
*/
|
||||
void
|
||||
format_set_font_scheme(lxw_format *self, const char *font_scheme)
|
||||
{
|
||||
LXW_FORMAT_FIELD_COPY(self->font_scheme, font_scheme);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_condense property.
|
||||
*/
|
||||
void
|
||||
format_set_font_condense(lxw_format *self)
|
||||
{
|
||||
self->font_condense = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the font_extend property.
|
||||
*/
|
||||
void
|
||||
format_set_font_extend(lxw_format *self)
|
||||
{
|
||||
self->font_extend = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the theme property.
|
||||
*/
|
||||
void
|
||||
format_set_theme(lxw_format *self, uint8_t value)
|
||||
{
|
||||
self->theme = value;
|
||||
}
|
218
src/hash_table.c
Normal file
@ -0,0 +1,218 @@
|
||||
/*****************************************************************************
|
||||
* hash_table - Hash table functions for libxlsxwriter.
|
||||
*
|
||||
* Used in conjunction with the libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "xlsxwriter/hash_table.h"
|
||||
|
||||
/*
|
||||
* Calculate the hash key using the FNV function. See:
|
||||
* http://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function
|
||||
*/
|
||||
size_t
|
||||
_generate_hash_key(void *data, size_t data_len, size_t num_buckets)
|
||||
{
|
||||
unsigned char *p = data;
|
||||
size_t hash = 2166136261;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < data_len; i++)
|
||||
hash = (hash * 16777619) ^ p[i];
|
||||
|
||||
return hash % num_buckets;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if an element exists in the hash table and return a pointer
|
||||
* to it if it does.
|
||||
*/
|
||||
lxw_hash_element *
|
||||
_hash_key_exists(lxw_hash_table *lxw_hash, void *key, size_t key_len)
|
||||
{
|
||||
size_t hash_key = _generate_hash_key(key, key_len, lxw_hash->num_buckets);
|
||||
struct lxw_hash_bucket_list *list;
|
||||
lxw_hash_element *element;
|
||||
|
||||
if (!lxw_hash->buckets[hash_key]) {
|
||||
/* The key isn't in the LXW_HASH hash table. */
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
/* The key is already in the table or there is a hash collision. */
|
||||
list = lxw_hash->buckets[hash_key];
|
||||
|
||||
/* Iterate over the keys in the bucket's linked list. */
|
||||
SLIST_FOREACH(element, list, lxw_hash_list_pointers) {
|
||||
if (memcmp(element->key, key, key_len) == 0) {
|
||||
/* The key already exists in the table. */
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
/* Key doesn't exist in the list so this is a hash collision. */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert or update a value in the LXW_HASH table based on a key
|
||||
* and return a pointer to the new or updated element.
|
||||
*/
|
||||
lxw_hash_element *
|
||||
_insert_hash_element(lxw_hash_table *lxw_hash, void *key, void *value,
|
||||
size_t key_len)
|
||||
{
|
||||
size_t hash_key = _generate_hash_key(key, key_len, lxw_hash->num_buckets);
|
||||
struct lxw_hash_bucket_list *list;
|
||||
lxw_hash_element *element;
|
||||
|
||||
if (!lxw_hash->buckets[hash_key]) {
|
||||
/* The key isn't in the LXW_HASH hash table. */
|
||||
|
||||
/* Create a linked list in the bucket to hold the lxw_hash keys. */
|
||||
list = calloc(1, sizeof(struct lxw_hash_bucket_list));
|
||||
RETURN_ON_MEM_ERROR(list, NULL);
|
||||
|
||||
/* Initialise the bucket linked list. */
|
||||
SLIST_INIT(list);
|
||||
|
||||
/* Create an lxw_hash element to add to the linked list. */
|
||||
element = calloc(1, sizeof(lxw_hash_element));
|
||||
RETURN_ON_MEM_ERROR(element, NULL);
|
||||
|
||||
/* Store the key and value. */
|
||||
element->key = key;
|
||||
element->value = value;
|
||||
|
||||
/* Add the lxw_hash element to the bucket's linked list. */
|
||||
SLIST_INSERT_HEAD(list, element, lxw_hash_list_pointers);
|
||||
|
||||
/* Also add it to the insertion order linked list. */
|
||||
STAILQ_INSERT_TAIL(lxw_hash->order_list, element,
|
||||
lxw_hash_order_pointers);
|
||||
|
||||
/* Store the bucket list at the hash index. */
|
||||
lxw_hash->buckets[hash_key] = list;
|
||||
|
||||
lxw_hash->used_buckets++;
|
||||
lxw_hash->unique_count++;
|
||||
|
||||
return element;
|
||||
}
|
||||
else {
|
||||
/* The key is already in the table or there is a hash collision. */
|
||||
list = lxw_hash->buckets[hash_key];
|
||||
|
||||
/* Iterate over the keys in the bucket's linked list. */
|
||||
SLIST_FOREACH(element, list, lxw_hash_list_pointers) {
|
||||
if (memcmp(element->key, key, key_len) == 0) {
|
||||
/* The key already exists in the table. Update the value. */
|
||||
if (lxw_hash->free_value)
|
||||
free(element->value);
|
||||
|
||||
element->value = value;
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
/* Key doesn't exist in the list so this is a hash collision.
|
||||
* Create an lxw_hash element to add to the linked list. */
|
||||
element = calloc(1, sizeof(lxw_hash_element));
|
||||
RETURN_ON_MEM_ERROR(element, NULL);
|
||||
|
||||
/* Store the key and value. */
|
||||
element->key = key;
|
||||
element->value = value;
|
||||
|
||||
/* Add the lxw_hash element to the bucket linked list. */
|
||||
SLIST_INSERT_HEAD(list, element, lxw_hash_list_pointers);
|
||||
|
||||
/* Also add it to the insertion order linked list. */
|
||||
STAILQ_INSERT_TAIL(lxw_hash->order_list, element,
|
||||
lxw_hash_order_pointers);
|
||||
|
||||
lxw_hash->unique_count++;
|
||||
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new LXW_HASH hash table object.
|
||||
*/
|
||||
lxw_hash_table *
|
||||
_new_lxw_hash(size_t num_buckets, uint8_t free_key, uint8_t free_value)
|
||||
{
|
||||
/* Create the new hash table. */
|
||||
lxw_hash_table *lxw_hash = calloc(1, sizeof(lxw_hash_table));
|
||||
RETURN_ON_MEM_ERROR(lxw_hash, NULL);
|
||||
|
||||
lxw_hash->free_key = free_key;
|
||||
lxw_hash->free_value = free_value;
|
||||
|
||||
/* Add the lxw_hash element buckets. */
|
||||
lxw_hash->buckets =
|
||||
calloc(num_buckets, sizeof(struct lxw_hash_bucket_list *));
|
||||
GOTO_LABEL_ON_MEM_ERROR(lxw_hash->buckets, mem_error);
|
||||
|
||||
/* Add a list for tracking the insertion order. */
|
||||
lxw_hash->order_list = calloc(1, sizeof(struct lxw_hash_order_list));
|
||||
GOTO_LABEL_ON_MEM_ERROR(lxw_hash->order_list, mem_error);
|
||||
|
||||
/* Initialise the order list. */
|
||||
STAILQ_INIT(lxw_hash->order_list);
|
||||
|
||||
/* Store the number of buckets to calculate the load factor. */
|
||||
lxw_hash->num_buckets = num_buckets;
|
||||
|
||||
return lxw_hash;
|
||||
|
||||
mem_error:
|
||||
if (lxw_hash)
|
||||
free(lxw_hash->order_list);
|
||||
|
||||
free(lxw_hash);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the LXW_HASH hash table object.
|
||||
*/
|
||||
void
|
||||
_free_lxw_hash(lxw_hash_table *lxw_hash)
|
||||
{
|
||||
size_t i;
|
||||
lxw_hash_element *element;
|
||||
lxw_hash_element *element_temp;
|
||||
|
||||
if (!lxw_hash)
|
||||
return;
|
||||
|
||||
/* Free the lxw_hash_elements and their data using the ordered linked list. */
|
||||
STAILQ_FOREACH_SAFE(element, lxw_hash->order_list,
|
||||
lxw_hash_order_pointers, element_temp) {
|
||||
if (lxw_hash->free_key)
|
||||
free(element->key);
|
||||
if (lxw_hash->free_value)
|
||||
free(element->value);
|
||||
free(element);
|
||||
}
|
||||
|
||||
/* Free the buckets from the hash table. */
|
||||
for (i = 0; i < lxw_hash->num_buckets; i++) {
|
||||
free(lxw_hash->buckets[i]);
|
||||
}
|
||||
|
||||
free(lxw_hash->order_list);
|
||||
free(lxw_hash->buckets);
|
||||
free(lxw_hash);
|
||||
}
|
456
src/packager.c
Normal file
@ -0,0 +1,456 @@
|
||||
/*****************************************************************************
|
||||
* packager - A library for creating Excel XLSX packager files.
|
||||
*
|
||||
* Used in conjunction with the libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter/xmlwriter.h"
|
||||
#include "xlsxwriter/packager.h"
|
||||
#include "xlsxwriter/hash_table.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
|
||||
int16_t _add_file_to_zip(lxw_packager *self, FILE * file,
|
||||
const char *filename);
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Private functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Create a new packager object.
|
||||
*/
|
||||
lxw_packager *
|
||||
_new_packager(const char *filename)
|
||||
{
|
||||
struct tm *file_date;
|
||||
time_t now = time(NULL);
|
||||
lxw_packager *packager = calloc(1, sizeof(lxw_packager));
|
||||
GOTO_LABEL_ON_MEM_ERROR(packager, mem_error);
|
||||
|
||||
packager->buffer = calloc(1, LXW_ZIP_BUFFER_SIZE);
|
||||
GOTO_LABEL_ON_MEM_ERROR(packager->buffer, mem_error);
|
||||
|
||||
packager->filename = __builtin_strdup(filename);
|
||||
GOTO_LABEL_ON_MEM_ERROR(packager->filename, mem_error);
|
||||
|
||||
packager->buffer_size = LXW_ZIP_BUFFER_SIZE;
|
||||
|
||||
/* Initialise the zip_fileinfo struct. */
|
||||
file_date = localtime(&now);
|
||||
packager->zipfile_info.tmz_date.tm_sec = file_date->tm_sec;
|
||||
packager->zipfile_info.tmz_date.tm_min = file_date->tm_min;
|
||||
packager->zipfile_info.tmz_date.tm_hour = file_date->tm_hour;
|
||||
packager->zipfile_info.tmz_date.tm_mday = file_date->tm_mday;
|
||||
packager->zipfile_info.tmz_date.tm_mon = file_date->tm_mon;
|
||||
packager->zipfile_info.tmz_date.tm_year = file_date->tm_year;
|
||||
packager->zipfile_info.dosDate = 0;
|
||||
packager->zipfile_info.internal_fa = 0;
|
||||
packager->zipfile_info.external_fa = 0;
|
||||
|
||||
/* Create a zip container for the xlsx file. */
|
||||
packager->zipfile = zipOpen(packager->filename, 0);
|
||||
if (packager->zipfile == NULL) {
|
||||
ERROR("Error opening zip file for xlsx");
|
||||
goto mem_error;
|
||||
}
|
||||
|
||||
return packager;
|
||||
|
||||
mem_error:
|
||||
_free_packager(packager);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a packager object.
|
||||
*/
|
||||
void
|
||||
_free_packager(lxw_packager *packager)
|
||||
{
|
||||
if (!packager)
|
||||
return;
|
||||
|
||||
free(packager->buffer);
|
||||
free(packager->filename);
|
||||
free(packager);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* File assembly functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
/*
|
||||
* Write the workbook.xml file.
|
||||
*/
|
||||
STATIC uint8_t
|
||||
_write_workbook_file(lxw_packager *self)
|
||||
{
|
||||
lxw_workbook *workbook = self->workbook;
|
||||
|
||||
workbook->file = tmpfile();
|
||||
|
||||
_workbook_assemble_xml_file(workbook);
|
||||
|
||||
_add_file_to_zip(self, workbook->file, "xl/workbook.xml");
|
||||
|
||||
fclose(workbook->file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the worksheet files.
|
||||
*/
|
||||
STATIC uint8_t
|
||||
_write_worksheet_files(lxw_packager *self)
|
||||
{
|
||||
lxw_workbook *workbook = self->workbook;
|
||||
lxw_worksheet *worksheet;
|
||||
char sheetname[FILENAME_LEN] = { 0 };
|
||||
uint16_t index = 1;
|
||||
|
||||
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
||||
__builtin_snprintf(sheetname, FILENAME_LEN,
|
||||
"xl/worksheets/sheet%d.xml", index++);
|
||||
|
||||
worksheet->file = tmpfile();
|
||||
|
||||
_worksheet_assemble_xml_file(worksheet);
|
||||
|
||||
_add_file_to_zip(self, worksheet->file, sheetname);
|
||||
|
||||
fclose(worksheet->file);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the sharedStrings.xml file.
|
||||
*/
|
||||
STATIC uint8_t
|
||||
_write_shared_strings_file(lxw_packager *self)
|
||||
{
|
||||
lxw_sst *sst = self->workbook->sst;
|
||||
|
||||
/* Skip the sharedStrings file if there are no shared strings. */
|
||||
if (!sst->string_count)
|
||||
return 0;
|
||||
|
||||
sst->file = tmpfile();
|
||||
|
||||
_sst_assemble_xml_file(sst);
|
||||
|
||||
_add_file_to_zip(self, sst->file, "xl/sharedStrings.xml");
|
||||
|
||||
fclose(sst->file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the app.xml file.
|
||||
*/
|
||||
STATIC uint8_t
|
||||
_write_app_file(lxw_packager *self)
|
||||
{
|
||||
lxw_workbook *workbook = self->workbook;
|
||||
lxw_worksheet *worksheet;
|
||||
lxw_app *app = _new_app();
|
||||
char num_sheets[ATTR_32] = { 0 };
|
||||
|
||||
app->file = tmpfile();
|
||||
|
||||
__builtin_snprintf(num_sheets, ATTR_32, "%d", self->workbook->num_sheets);
|
||||
|
||||
_add_heading_pair(app, "Worksheets", num_sheets);
|
||||
|
||||
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
||||
_add_part_name(app, worksheet->name);
|
||||
}
|
||||
|
||||
_app_assemble_xml_file(app);
|
||||
|
||||
_add_file_to_zip(self, app->file, "docProps/app.xml");
|
||||
|
||||
fclose(app->file);
|
||||
|
||||
_free_app(app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the core.xml file.
|
||||
*/
|
||||
STATIC uint8_t
|
||||
_write_core_file(lxw_packager *self)
|
||||
{
|
||||
lxw_core *core = _new_core();
|
||||
|
||||
core->file = tmpfile();
|
||||
|
||||
core->properties = self->workbook->properties;
|
||||
|
||||
_core_assemble_xml_file(core);
|
||||
|
||||
_add_file_to_zip(self, core->file, "docProps/core.xml");
|
||||
|
||||
fclose(core->file);
|
||||
|
||||
_free_core(core);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the theme.xml file.
|
||||
*/
|
||||
STATIC uint8_t
|
||||
_write_theme_file(lxw_packager *self)
|
||||
{
|
||||
lxw_theme *theme = _new_theme();
|
||||
|
||||
theme->file = tmpfile();
|
||||
|
||||
_theme_assemble_xml_file(theme);
|
||||
|
||||
_add_file_to_zip(self, theme->file, "xl/theme/theme1.xml");
|
||||
|
||||
fclose(theme->file);
|
||||
|
||||
_free_theme(theme);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the styles.xml file.
|
||||
*/
|
||||
STATIC uint8_t
|
||||
_write_styles_file(lxw_packager *self)
|
||||
{
|
||||
lxw_styles *styles = _new_styles();
|
||||
lxw_hash_element *hash_element;
|
||||
|
||||
/* Copy the unique and in-use formats from the workbook xf_format_indices
|
||||
* list to the styles xf_format list. */
|
||||
STAILQ_FOREACH(hash_element,
|
||||
self->workbook->xf_format_indices->order_list,
|
||||
lxw_hash_order_pointers) {
|
||||
lxw_format *workbook_format = (lxw_format *) hash_element->value;
|
||||
lxw_format *style_format = _new_format();
|
||||
memcpy(style_format, workbook_format, sizeof(lxw_format));
|
||||
STAILQ_INSERT_TAIL(styles->xf_formats, style_format, list_pointers);
|
||||
}
|
||||
|
||||
styles->font_count = self->workbook->font_count;
|
||||
styles->border_count = self->workbook->border_count;
|
||||
styles->fill_count = self->workbook->fill_count;
|
||||
styles->num_format_count = self->workbook->num_format_count;
|
||||
styles->xf_count = self->workbook->xf_format_indices->unique_count;
|
||||
|
||||
styles->file = tmpfile();
|
||||
|
||||
_styles_assemble_xml_file(styles);
|
||||
|
||||
_add_file_to_zip(self, styles->file, "xl/styles.xml");
|
||||
|
||||
fclose(styles->file);
|
||||
|
||||
_free_styles(styles);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the ContentTypes.xml file.
|
||||
*/
|
||||
STATIC uint8_t
|
||||
_write_content_types_file(lxw_packager *self)
|
||||
{
|
||||
lxw_content_types *content_types = _new_content_types();
|
||||
lxw_workbook *workbook = self->workbook;
|
||||
lxw_worksheet *worksheet;
|
||||
char sheetname[FILENAME_LEN] = { 0 };
|
||||
uint16_t index = 1;
|
||||
|
||||
content_types->file = tmpfile();
|
||||
|
||||
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
||||
__builtin_snprintf(sheetname, FILENAME_LEN, "sheet%d", index++);
|
||||
_ct_add_worksheet_name(content_types, sheetname);
|
||||
}
|
||||
|
||||
if (workbook->sst->string_count)
|
||||
_ct_add_shared_strings(content_types);
|
||||
|
||||
_content_types_assemble_xml_file(content_types);
|
||||
|
||||
_add_file_to_zip(self, content_types->file, "[Content_Types].xml");
|
||||
|
||||
fclose(content_types->file);
|
||||
|
||||
_free_content_types(content_types);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the workbook .rels xml file.
|
||||
*/
|
||||
STATIC uint8_t
|
||||
_write_workbook_rels_file(lxw_packager *self)
|
||||
{
|
||||
lxw_relationships *rels = _new_relationships();
|
||||
lxw_workbook *workbook = self->workbook;
|
||||
lxw_worksheet *worksheet;
|
||||
char sheetname[FILENAME_LEN] = { 0 };
|
||||
uint16_t index = 1;
|
||||
|
||||
rels->file = tmpfile();
|
||||
|
||||
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
|
||||
__builtin_snprintf(sheetname, FILENAME_LEN, "worksheets/sheet%d.xml",
|
||||
index++);
|
||||
_add_document_relationship(rels, "/worksheet", sheetname);
|
||||
}
|
||||
|
||||
_add_document_relationship(rels, "/theme", "theme/theme1.xml");
|
||||
_add_document_relationship(rels, "/styles", "styles.xml");
|
||||
|
||||
if (workbook->sst->string_count)
|
||||
_add_document_relationship(rels, "/sharedStrings",
|
||||
"sharedStrings.xml");
|
||||
|
||||
_relationships_assemble_xml_file(rels);
|
||||
|
||||
_add_file_to_zip(self, rels->file, "xl/_rels/workbook.xml.rels");
|
||||
|
||||
fclose(rels->file);
|
||||
_free_relationships(rels);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the _rels/.rels xml file.
|
||||
*/
|
||||
STATIC uint8_t
|
||||
_write_root_rels_file(lxw_packager *self)
|
||||
{
|
||||
lxw_relationships *rels = _new_relationships();
|
||||
|
||||
rels->file = tmpfile();
|
||||
|
||||
_add_document_relationship(rels, "/officeDocument", "xl/workbook.xml");
|
||||
_add_package_relationship(rels, "/metadata/core-properties",
|
||||
"docProps/core.xml");
|
||||
_add_document_relationship(rels, "/extended-properties",
|
||||
"docProps/app.xml");
|
||||
|
||||
_relationships_assemble_xml_file(rels);
|
||||
|
||||
_add_file_to_zip(self, rels->file, "_rels/.rels");
|
||||
|
||||
fclose(rels->file);
|
||||
|
||||
_free_relationships(rels);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Public functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int16_t
|
||||
_add_file_to_zip(lxw_packager *self, FILE * file, const char *filename)
|
||||
{
|
||||
int16_t error = ZIP_OK;
|
||||
size_t size_read;
|
||||
|
||||
error = zipOpenNewFileInZip4_64(self->zipfile,
|
||||
filename,
|
||||
&self->zipfile_info,
|
||||
NULL, 0, NULL, 0, NULL,
|
||||
Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0,
|
||||
-MAX_WBITS, DEF_MEM_LEVEL,
|
||||
Z_DEFAULT_STRATEGY, NULL, 0, 0, 0, 0);
|
||||
|
||||
if (error != ZIP_OK) {
|
||||
ERROR("Error adding member to zipfile");
|
||||
return error;
|
||||
}
|
||||
|
||||
fflush(file);
|
||||
rewind(file);
|
||||
|
||||
size_read = fread(self->buffer, 1, self->buffer_size, file);
|
||||
|
||||
while (size_read) {
|
||||
|
||||
if (size_read < self->buffer_size) {
|
||||
if (feof(file) == 0) {
|
||||
ERROR("Error reading member file data");
|
||||
return ZIP_ERRNO;
|
||||
}
|
||||
}
|
||||
|
||||
error = zipWriteInFileInZip(self->zipfile, self->buffer, size_read);
|
||||
if (error < 0) {
|
||||
ERROR("Error in writing member in the zipfile");
|
||||
return error;
|
||||
}
|
||||
|
||||
size_read = fread(self->buffer, 1, self->buffer_size, file);
|
||||
}
|
||||
|
||||
if (error < 0) {
|
||||
return ZIP_ERRNO;
|
||||
}
|
||||
else {
|
||||
error = zipCloseFileInZip(self->zipfile);
|
||||
if (error != ZIP_OK) {
|
||||
ERROR("Error in closing member in the zipfile");
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return ZIP_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the xml files that make up the XLXS OPC package.
|
||||
*/
|
||||
uint8_t
|
||||
_create_package(lxw_packager *self)
|
||||
{
|
||||
|
||||
_write_workbook_file(self);
|
||||
_write_worksheet_files(self);
|
||||
_write_shared_strings_file(self);
|
||||
_write_app_file(self);
|
||||
_write_core_file(self);
|
||||
_write_theme_file(self);
|
||||
_write_styles_file(self);
|
||||
_write_content_types_file(self);
|
||||
_write_workbook_rels_file(self);
|
||||
_write_root_rels_file(self);
|
||||
|
||||
zipClose(self->zipfile, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
242
src/relationships.c
Normal file
@ -0,0 +1,242 @@
|
||||
/*****************************************************************************
|
||||
* relationships - A library for creating Excel XLSX relationships files.
|
||||
*
|
||||
* Used in conjunction with the libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "xlsxwriter/xmlwriter.h"
|
||||
#include "xlsxwriter/relationships.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Private functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Create a new relationships object.
|
||||
*/
|
||||
lxw_relationships *
|
||||
_new_relationships()
|
||||
{
|
||||
lxw_relationships *rels = calloc(1, sizeof(lxw_relationships));
|
||||
GOTO_LABEL_ON_MEM_ERROR(rels, mem_error);
|
||||
|
||||
rels->relationships = calloc(1, sizeof(struct lxw_rel_tuples));
|
||||
GOTO_LABEL_ON_MEM_ERROR(rels->relationships, mem_error);
|
||||
STAILQ_INIT(rels->relationships);
|
||||
|
||||
return rels;
|
||||
|
||||
mem_error:
|
||||
_free_relationships(rels);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a relationships object.
|
||||
*/
|
||||
void
|
||||
_free_relationships(lxw_relationships *rels)
|
||||
{
|
||||
lxw_rel_tuple *relationship;
|
||||
|
||||
if (!rels)
|
||||
return;
|
||||
|
||||
while (!STAILQ_EMPTY(rels->relationships)) {
|
||||
relationship = STAILQ_FIRST(rels->relationships);
|
||||
STAILQ_REMOVE_HEAD(rels->relationships, list_pointers);
|
||||
free(relationship->type);
|
||||
free(relationship->target);
|
||||
free(relationship->target_mode);
|
||||
free(relationship);
|
||||
}
|
||||
|
||||
free(rels->relationships);
|
||||
free(rels);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Write the XML declaration.
|
||||
*/
|
||||
STATIC void
|
||||
_relationships_xml_declaration(lxw_relationships *self)
|
||||
{
|
||||
_xml_declaration(self->file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <Relationship> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_relationship(lxw_relationships *self, const char *type,
|
||||
const char *target, const char *target_mode)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
char r_id[MAX_ATTRIBUTE_LENGTH] = { 0 };
|
||||
|
||||
self->rel_id++;
|
||||
__builtin_snprintf(r_id, ATTR_32, "rId%d", self->rel_id);
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_STR("Id", r_id);
|
||||
_PUSH_ATTRIBUTES_STR("Type", type);
|
||||
_PUSH_ATTRIBUTES_STR("Target", target);
|
||||
|
||||
if (target_mode)
|
||||
_PUSH_ATTRIBUTES_STR("TargetMode", target_mode);
|
||||
|
||||
_xml_empty_tag(self->file, "Relationship", &attributes);
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <Relationships> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_relationships(lxw_relationships *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
lxw_rel_tuple *rel;
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_STR("xmlns", LXW_PACKAGE_SCHEMA);
|
||||
|
||||
_xml_start_tag(self->file, "Relationships", &attributes);
|
||||
|
||||
STAILQ_FOREACH(rel, self->relationships, list_pointers) {
|
||||
_write_relationship(self, rel->type, rel->target, rel->target_mode);
|
||||
}
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML file assembly functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Assemble and write the XML file.
|
||||
*/
|
||||
void
|
||||
_relationships_assemble_xml_file(lxw_relationships *self)
|
||||
{
|
||||
/* Write the XML declaration. */
|
||||
_relationships_xml_declaration(self);
|
||||
|
||||
_write_relationships(self);
|
||||
|
||||
/* Close the relationships tag. */
|
||||
_xml_end_tag(self->file, "Relationships");
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a generic container relationship to XLSX .rels xml files.
|
||||
*/
|
||||
STATIC void
|
||||
_add_relationship(lxw_relationships *self, const char *schema,
|
||||
const char *type, const char *target,
|
||||
const char *target_mode)
|
||||
{
|
||||
lxw_rel_tuple *relationship;
|
||||
|
||||
if (!schema || !type || !target)
|
||||
return;
|
||||
|
||||
relationship = calloc(1, sizeof(lxw_rel_tuple));
|
||||
GOTO_LABEL_ON_MEM_ERROR(relationship, mem_error);
|
||||
|
||||
relationship->type = calloc(1, MAX_ATTRIBUTE_LENGTH);
|
||||
GOTO_LABEL_ON_MEM_ERROR(relationship->type, mem_error);
|
||||
|
||||
/* Add the schema to the relationship type. */
|
||||
__builtin_snprintf(relationship->type, MAX_ATTRIBUTE_LENGTH, "%s%s",
|
||||
schema, type);
|
||||
|
||||
relationship->target = __builtin_strdup(target);
|
||||
GOTO_LABEL_ON_MEM_ERROR(relationship->target, mem_error);
|
||||
|
||||
if (target_mode) {
|
||||
relationship->target_mode = __builtin_strdup(target_mode);
|
||||
GOTO_LABEL_ON_MEM_ERROR(relationship->target_mode, mem_error);
|
||||
}
|
||||
|
||||
STAILQ_INSERT_TAIL(self->relationships, relationship, list_pointers);
|
||||
|
||||
return;
|
||||
|
||||
mem_error:
|
||||
if (relationship) {
|
||||
free(relationship->type);
|
||||
free(relationship->target);
|
||||
free(relationship->target_mode);
|
||||
free(relationship);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Public functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Add a document relationship to XLSX .rels xml files.
|
||||
*/
|
||||
void
|
||||
_add_document_relationship(lxw_relationships *self, const char *type,
|
||||
const char *target)
|
||||
{
|
||||
_add_relationship(self, LXW_DOCUMENT_SCHEMA, type, target, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a package relationship to XLSX .rels xml files.
|
||||
*/
|
||||
void
|
||||
_add_package_relationship(lxw_relationships *self, const char *type,
|
||||
const char *target)
|
||||
{
|
||||
_add_relationship(self, LXW_PACKAGE_SCHEMA, type, target, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a MS schema package relationship to XLSX .rels xml files.
|
||||
*/
|
||||
void
|
||||
_add_ms_package_relationship(lxw_relationships *self, const char *type,
|
||||
const char *target)
|
||||
{
|
||||
_add_relationship(self, LXW_MS_SCHEMA, type, target, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a worksheet relationship to sheet .rels xml files.
|
||||
*/
|
||||
void
|
||||
_add_worksheet_relationship(lxw_relationships *self, const char *type,
|
||||
const char *target, const char *target_mode)
|
||||
{
|
||||
_add_relationship(self, LXW_DOCUMENT_SCHEMA, type, target, target_mode);
|
||||
}
|
306
src/shared_strings.c
Normal file
@ -0,0 +1,306 @@
|
||||
/*****************************************************************************
|
||||
* shared_strings - A library for creating Excel XLSX sst files.
|
||||
*
|
||||
* Used in conjunction with the libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter/xmlwriter.h"
|
||||
#include "xlsxwriter/shared_strings.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Private functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Create a new SST SharedString hash table object.
|
||||
*/
|
||||
lxw_sst *
|
||||
_new_sst()
|
||||
{
|
||||
/* Create the new hash table. */
|
||||
lxw_sst *sst = calloc(1, sizeof(lxw_sst));
|
||||
RETURN_ON_MEM_ERROR(sst, NULL);
|
||||
|
||||
/* Add the sst element buckets. */
|
||||
sst->buckets = calloc(NUM_SST_BUCKETS, sizeof(struct sst_bucket_list *));
|
||||
GOTO_LABEL_ON_MEM_ERROR(sst->buckets, mem_error1);
|
||||
|
||||
/* Add a list for tracking the insertion order. */
|
||||
sst->order_list = calloc(1, sizeof(struct sst_order_list));
|
||||
GOTO_LABEL_ON_MEM_ERROR(sst->order_list, mem_error2);
|
||||
|
||||
/* Initialise the order list. */
|
||||
STAILQ_INIT(sst->order_list);
|
||||
|
||||
/* Store the number of buckets to calculate the load factor. */
|
||||
sst->num_buckets = NUM_SST_BUCKETS;
|
||||
|
||||
return sst;
|
||||
|
||||
mem_error2:
|
||||
free(sst->order_list);
|
||||
|
||||
mem_error1:
|
||||
free(sst);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a SST SharedString hash table object.
|
||||
*/
|
||||
void
|
||||
_free_sst(lxw_sst *sst)
|
||||
{
|
||||
size_t i;
|
||||
struct sst_element *sst_element;
|
||||
struct sst_element *sst_element_temp;
|
||||
|
||||
if (!sst)
|
||||
return;
|
||||
|
||||
/* Free the sst_elements and their data using the ordered linked list. */
|
||||
STAILQ_FOREACH_SAFE(sst_element, sst->order_list, sst_order_pointers,
|
||||
sst_element_temp) {
|
||||
if (sst_element && sst_element->string)
|
||||
free(sst_element->string);
|
||||
if (sst_element)
|
||||
free(sst_element);
|
||||
}
|
||||
|
||||
/* Free the buckets from the hash table. */
|
||||
for (i = 0; i < sst->num_buckets; i++) {
|
||||
if (sst->buckets[i])
|
||||
free(sst->buckets[i]);
|
||||
}
|
||||
|
||||
if (sst->order_list)
|
||||
free(sst->order_list);
|
||||
|
||||
if (sst->buckets)
|
||||
free(sst->buckets);
|
||||
|
||||
free(sst);
|
||||
}
|
||||
|
||||
/*
|
||||
* FNV hash function for SST table string keys. See:
|
||||
* http://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function
|
||||
*/
|
||||
size_t
|
||||
_generate_sst_hash_key(const char *string)
|
||||
{
|
||||
size_t string_len = strlen(string);
|
||||
size_t hash = 2166136261;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < string_len; i++)
|
||||
hash = (hash * 16777619) ^ (unsigned char) string[i];
|
||||
|
||||
return hash % NUM_SST_BUCKETS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
/*
|
||||
* Write the XML declaration.
|
||||
*/
|
||||
STATIC void
|
||||
_sst_xml_declaration(lxw_sst *self)
|
||||
{
|
||||
_xml_declaration(self->file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <t> element.
|
||||
*/
|
||||
void
|
||||
_write_t(lxw_sst *self, char *string)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
|
||||
/* Add attribute to preserve leading or trailing whitespace. */
|
||||
if (string && (isspace(string[0]) || isspace(string[strlen(string) - 1])))
|
||||
_PUSH_ATTRIBUTES_STR("xml:space", "preserve");
|
||||
|
||||
_xml_data_element(self->file, "t", string, &attributes);
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <si> element.
|
||||
*/
|
||||
void
|
||||
_write_si(lxw_sst *self, char *string)
|
||||
{
|
||||
_xml_start_tag(self->file, "si", NULL);
|
||||
|
||||
/* Write the t element. */
|
||||
_write_t(self, string);
|
||||
|
||||
_xml_end_tag(self->file, "si");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <sst> element.
|
||||
*/
|
||||
void
|
||||
_write_sst(lxw_sst *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
char xmlns[] =
|
||||
"http://schemas.openxmlformats.org/spreadsheetml/2006/main";
|
||||
|
||||
_INIT_ATTRIBUTES();
|
||||
_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
|
||||
_PUSH_ATTRIBUTES_INT("count", self->string_count);
|
||||
_PUSH_ATTRIBUTES_INT("uniqueCount", self->unique_count);
|
||||
|
||||
_xml_start_tag(self->file, "sst", &attributes);
|
||||
|
||||
_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML file assembly functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Assemble and write the XML file.
|
||||
*/
|
||||
void
|
||||
_write_sst_strings(lxw_sst *self)
|
||||
{
|
||||
struct sst_element *sst_element;
|
||||
|
||||
STAILQ_FOREACH(sst_element, self->order_list, sst_order_pointers) {
|
||||
/* Write the si element. */
|
||||
_write_si(self, sst_element->string);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Assemble and write the XML file.
|
||||
*/
|
||||
void
|
||||
_sst_assemble_xml_file(lxw_sst *self)
|
||||
{
|
||||
/* Write the XML declaration. */
|
||||
_sst_xml_declaration(self);
|
||||
|
||||
/* Write the sst element. */
|
||||
_write_sst(self);
|
||||
|
||||
/* Write the sst strings. */
|
||||
_write_sst_strings(self);
|
||||
|
||||
/* Close the sst tag. */
|
||||
_xml_end_tag(self->file, "sst");
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Public functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
/*
|
||||
* Add to or find a string in the SST SharedString table and return it's index.
|
||||
*/
|
||||
int32_t
|
||||
_get_sst_index(lxw_sst *sst, const char *string)
|
||||
{
|
||||
size_t hash_key = _generate_sst_hash_key(string);
|
||||
struct sst_bucket_list *list;
|
||||
struct sst_element *element;
|
||||
|
||||
if (!sst->buckets[hash_key]) {
|
||||
/* The string isn't in the SST SharedString hash table. */
|
||||
|
||||
/* Create a linked list in the bucket to hold the sst strings. */
|
||||
list = calloc(1, sizeof(struct sst_bucket_list));
|
||||
RETURN_ON_MEM_ERROR(list, -1);
|
||||
|
||||
/* Initialise the bucket linked list. */
|
||||
SLIST_INIT(list);
|
||||
|
||||
/* Create an sst element to add to the linked list. */
|
||||
element = calloc(1, sizeof(struct sst_element));
|
||||
RETURN_ON_MEM_ERROR(element, -1);
|
||||
|
||||
/* Store the string and its index. */
|
||||
element->index = sst->unique_count;
|
||||
element->string = __builtin_strdup(string);
|
||||
|
||||
/* Add the sst element to the bucket linked list. */
|
||||
SLIST_INSERT_HEAD(list, element, sst_list_pointers);
|
||||
|
||||
/* Also add it to the insertion order linked list. */
|
||||
STAILQ_INSERT_TAIL(sst->order_list, element, sst_order_pointers);
|
||||
|
||||
/* Store the bucket list at the hash index. */
|
||||
sst->buckets[hash_key] = list;
|
||||
|
||||
/* Update the bucket and SST string counts. */
|
||||
sst->used_buckets++;
|
||||
sst->string_count++;
|
||||
sst->unique_count++;
|
||||
|
||||
return element->index;
|
||||
}
|
||||
else {
|
||||
/* The sting is already in the table or there is a hash collision. */
|
||||
list = sst->buckets[hash_key];
|
||||
|
||||
/* Iterate over the strings in the bucket's linked list. */
|
||||
SLIST_FOREACH(element, list, sst_list_pointers) {
|
||||
if (strcmp(element->string, string) == 0) {
|
||||
/* The string already exists in the table. Update the
|
||||
* non-unique string count and return the index. */
|
||||
sst->string_count++;
|
||||
return element->index;
|
||||
}
|
||||
}
|
||||
|
||||
/* String doesn't exist in the list so this is a hash collision.
|
||||
* Create an sst element to add to the linked list. */
|
||||
element = calloc(1, sizeof(struct sst_element));
|
||||
RETURN_ON_MEM_ERROR(element, -1);
|
||||
|
||||
/* Store the string and its index. */
|
||||
element->index = sst->unique_count;
|
||||
element->string = __builtin_strdup(string);
|
||||
|
||||
/* Add the sst element to the bucket linked list. */
|
||||
SLIST_INSERT_HEAD(list, element, sst_list_pointers);
|
||||
|
||||
/* Also add it to the insertion order linked list. */
|
||||
STAILQ_INSERT_TAIL(sst->order_list, element, sst_order_pointers);
|
||||
|
||||
/* Update the SST string counts. */
|
||||
sst->string_count++;
|
||||
sst->unique_count++;
|
||||
|
||||
return element->index;
|
||||
}
|
||||
}
|
1088
src/styles.c
Normal file
81
src/theme.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*****************************************************************************
|
||||
* theme - A library for creating Excel XLSX theme files.
|
||||
*
|
||||
* Used in conjunction with the libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter/xmlwriter.h"
|
||||
#include "xlsxwriter/theme.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Woverlength-strings"
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Private functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Create a new theme object.
|
||||
*/
|
||||
lxw_theme *
|
||||
_new_theme()
|
||||
{
|
||||
lxw_theme *theme = calloc(1, sizeof(lxw_theme));
|
||||
GOTO_LABEL_ON_MEM_ERROR(theme, mem_error);
|
||||
|
||||
return theme;
|
||||
|
||||
mem_error:
|
||||
_free_theme(theme);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a theme object.
|
||||
*/
|
||||
void
|
||||
_free_theme(lxw_theme *theme)
|
||||
{
|
||||
if (!theme)
|
||||
return;
|
||||
|
||||
free(theme);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* This library isn't a xmlwriter. */
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML file assembly functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Assemble and write the XML file.
|
||||
*/
|
||||
void
|
||||
_theme_assemble_xml_file(lxw_theme *self)
|
||||
{
|
||||
fputs(THEME_DATA, self->file);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Public functions.
|
||||
*
|
||||
****************************************************************************/
|