功能: 服务端生成完整报告并保护单任务

- 使用 libxlsxwriter 常量内存导出 Excel\n- 增加全局任务占用提示与原始数据持久化\n- 保留运行时任务数据并更新接口文档
This commit is contained in:
cloud
2026-08-05 16:47:31 +08:00
parent 07274797af
commit 99ed321d24
2292 changed files with 134317 additions and 126 deletions
+27
View File
@@ -0,0 +1,27 @@
/**
@page author Author
Libxlsxwriter was written by John McNamara.
- [GitHub](https://github.com/jmcnamara)
- [Twitter \@jmcnamara13](https://twitter.com/jmcnamara13)
@section donations Sponsorship and Donations
I write and maintain a series of open source libraries for creating Excel
files. The most commonly used are XlsxWriter in Python, Libxlsxwriter in C and
Excel::Writer::XLSX and Spreadsheet::WriteExcel in Perl.
My aim is to write well documented and well tested code that does what the
user needs and doesn't get in their way. You can help make this continue, or
show your appreciation for work to date, by becoming a
[GitHub Sponsor](https://github.com/sponsors/jmcnamara).
Or make a one-off donation via
[PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ATE9EFWNF7PBJ).
Next: @ref license
*/
+153
View File
@@ -0,0 +1,153 @@
/**
@page bugs Known Issues and Bugs
@tableofcontents
This section lists known issues and bugs and gives some information on
how to submit bug reports.
@section bugs_unreadable Content is Unreadable. Open and Repair
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).
@section bugs_formula_name 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:
@code
worksheet_write_formula(worksheet, 0, 0,"=_xlfn.STDEV.S(B1:B10)", NULL);
@endcode
See also @ref working_with_formulas.
@section bugs_formula_zero 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.
See also @ref working_with_formulas.
@section bugs_images Images not displayed correctly in Excel 2001 for Mac and non-Excel applications
Images inserted into worksheets via `worksheet_insert_image()` may not display
correctly in Excel 2011 for Mac and non-Excel applications such as OpenOffice
and LibreOffice. Specifically the images may looked stretched or squashed.
This is not an XlsxWriter issue. It also occurs with files created in Excel
2007 and Excel 2010.
@section bugs_reporting Reporting Bugs
Here are some tips on reporting bugs in `libxlsxwriter`.
@subsection bugs_upgrade 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
@subsection bugs_docs Read the documentation
Read or search the `libxlsxwriter` documentation to see if the issue you are
encountering is already explained.
@subsection bugs_examples 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.
@subsection bugs_issues Use the xlsxwriter Issue tracker
The [libxlsxwriter issue tracker]
(https://github.com/jmcnamara/libxlsxwriter/issues) is on GitHub.
@subsection bugs_tips 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 analyze 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 = workbook_new("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"
*/
File diff suppressed because it is too large Load Diff
+620
View File
@@ -0,0 +1,620 @@
##############################################################
@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.
@image html hello01.png
##############################################################
@example anatomy.c
Anatomy of a simple libxlsxwriter program where the program is explained line
by line with comments.
@image html anatomy.png
##############################################################
@example demo.c
A simple example of some of the features of the libxlsxwriter library.
@image html demo.png
##############################################################
@example format_font.c
Example of writing some data with font formatting to a simple Excel
file using libxlsxwriter.
@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.
@image html format_set_num_format.png
##############################################################
@example tutorial1.c
A tutorial program which is shown, with explanations, in @ref tutorial01.
@image html tutorial01.png
##############################################################
@example tutorial2.c
A tutorial program which is shown, with explanations, in @ref tutorial02.
@image html tutorial02.png
##############################################################
@example tutorial3.c
A tutorial program which is shown, with explanations, in @ref tutorial03.
@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.
@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.
@image html date_example02.png
##############################################################
@example dates_and_times03.c
Example of writing dates and times in Excel using Unix datetimes and
formatting.
@image html date_example03.png
##############################################################
@example dates_and_times04.c
Example of writing dates and times in Excel using different date formats.
@image html date_example04.png
##############################################################
@example hyperlinks.c
Example of writing urls/hyperlinks to a worksheet.
@image html hyperlinks.png
##############################################################
@example rich_strings.c
Example of writing "rich" multi-format strings to a worksheet.
@image html rich_strings.png
##############################################################
@example array_formula.c
Example of writing array formulas to a worksheet.
@image html array_formula.png
##############################################################
@example dynamic_arrays.c
Example of writing Excel 365 dynamic array formulas to a worksheet.
@image html dynamic_arrays01.png
##############################################################
@example utf8.c
A simple Unicode UTF-8 example. Note, the source file is UTF-8 encoded.
@image html utf8.png
##############################################################
@example constant_memory.c
Example of using libxlsxwriter for writing large files in constant memory
mode.
@image html constant_memory.png
##############################################################
@example output_buffer.c
Example of using libxlsxwriter to write a workbook file to a memory buffer.
@image html hello01.png
##############################################################
@example image_buffer.c
Example of adding an image to a worksheet from a memory buffer.
@image html image_buffer2.png
##############################################################
@example merge_range.c
Example of merging cells in a worksheet.
@image html merge_range.png
##############################################################
@example merge_rich_string.c
Example of merging cells with a rich string in a worksheet.
@image html merge_rich.png
##############################################################
@example autofilter.c
Example of adding autofilters to a worksheets and adding filter conditions.
@image html autofilter3.png
##############################################################
@example data_validate.c
Example of adding data validations to a worksheet.
@image html data_validate4.png
##############################################################
@example conditional_format1.c
A simple example of how to add a conditional format a
libxlsxwriter file. Conditional formatting allows you to apply
a format to a cell or a range of cells based on certain criteria.
@image html conditional_format12.png
##############################################################
@example conditional_format2.c
A more comprehensive example of how to add conditional formatting
to an libxlsxwriter file. Conditional formatting allows you to
apply a format to a cell or a range of cells based on certain
criteria.
@image html conditional_format1.png
##############################################################
@example tables.c
Example of how to add tables to a worksheet. Tables in Excel are used to group
rows and columns of data into a single structure that can be referenced in a
formula or formatted collectively.
@image html tables12.png
##############################################################
@example images.c
Example of adding images to a worksheet.
@image html images.png
##############################################################
@example headers_footers.c
Example of adding worksheet headers and footers to worksheets.
@image html headers_footers.png
##############################################################
@example defined_name.c
Example of how to create defined names (named ranges) using libxlsxwriter.
Defined names are used to define descriptive names to represent a value, a
single cell or a range of cells in a workbook or worksheet.
@image html defined_name.png
##############################################################
@example outline.c
Example of how to generate Excel outlines and grouping.
@image html outline1.png
##############################################################
@example outline_collapsed.c
Example of how to generate Excel outlines and grouping. These examples focus
mainly on collapsed outlines.
@image html outline2.png
##############################################################
@example watermark.c
Example of how to a watermark image for a worksheet using the method suggested
in the Microsoft documentation:
https://support.microsoft.com/en-us/office/add-a-watermark-in-excel-a372182a-d733-484e-825c-18ddf3edf009
@image html worksheet_watermark.png
##############################################################
@example background.c
Example of how to set the background image for a worksheet.
@image html background.png
##############################################################
@example tab_colors.c
Example of how to set Excel worksheet tab colors.
@image html tab_colors.png
##############################################################
@example diagonal_border.c
Example of how to set a worksheet cell diagonal border.
@image html diagonal_border.png
##############################################################
@example hide_sheet.c
Example of how to hide an Excel worksheet.
@image html hide_sheet.png
##############################################################
@example doc_properties.c
Example of setting Excel document properties.
@image html doc_properties.png
##############################################################
@example doc_custom_properties.c
Example of setting Excel custom document properties, i.e., properties
non-standard document properties.
@image html custom_properties.png
##############################################################
@example worksheet_protection.c
Example of setting Excel worksheet protection.
@image html worksheet_protection.png
##############################################################
@example macro.c
Example adding a VBA macro to a workbook.
@image html macros.png
##############################################################
@example comments1.c
A simple example of adding cell comments to a worksheet.
@image html comments1.png
##############################################################
@example comments2.c
Another example of adding cell comments to a worksheet. This example
demonstrates most of the available comment formatting options.
@image html comments2.png
##############################################################
@example hide_row_col.c
Example of hiding rows and columns in an Excel worksheet.
@image html hide_row_col.png
##############################################################
@example panes.c
An example of how to create panes in a worksheet, both "freeze" panes and
"split" panes.
@image html panes.png
##############################################################
@example ignore_errors.c
Example of hiding worksheet errors and warnings.
@image html ignore_errors2.png
##############################################################
@example lambda.c
Example of using the new Excel `LAMBDA()` function. It demonstrates how to
create a lambda function in Excel and also how to assign a name to it so that
it can be called as a user defined function. This particular example converts
from Fahrenheit to Celsius.
@image html lambda01.png
##############################################################
@example chart.c
An example of creating a simple column chart with 3 data series.
@image html chart_simple.png
##############################################################
@example chart_area.c
Example of creating Excel Area charts. Three types of area chart are shown.
The default area chart:
@image html chart_area1.png
Stacked area chart:
@image html chart_area2.png
Percent stacked area chart:
@image html chart_area3.png
##############################################################
@example chart_bar.c
Example of creating Excel Bar charts. Three types of bar chart are shown.
The default bar chart:
@image html chart_bar1.png
Stacked bar chart:
@image html chart_bar2.png
Percent stacked bar chart:
@image html chart_bar3.png
##############################################################
@example chart_column.c
Example of creating Excel Column charts. Three types of column chart are shown.
The default column chart:
@image html chart_column1.png
Stacked column chart:
@image html chart_column2.png
Percent stacked column chart:
@image html chart_column3.png
##############################################################
@example chart_line.c
Example of creating Excel Line charts. Three types of line chart are shown.
The default line chart:
@image html chart_line1.png
Stacked line chart:
@image html chart_line2.png
Percent stacked line chart:
@image html chart_line3.png
##############################################################
@example chart_scatter.c
Example of creating Excel Scatter charts. Five types of scatter chart are shown.
The default scatter chart:
@image html chart_scatter1.png
Straight scatter chart with markers:
@image html chart_scatter2.png
Straight scatter chart:
@image html chart_scatter3.png
Smooth scatter chart with markers:
@image html chart_scatter4.png
Smooth scatter chart:
@image html chart_scatter5.png
##############################################################
@example chart_radar.c
Example of creating Excel Radar charts. Three types of radar chart are shown.
The default radar chart:
@image html chart_radar1.png
Radar chart with markers:
@image html chart_radar2.png
Filled radar chart:
@image html chart_radar3.png
##############################################################
@example chart_pie.c
Examples of creating an Excel Pie chart.
The default pie chart:
@image html chart_pie1.png
A pie chart with user defined colors:
@image html chart_pie2.png
A pie chart with rotated segments:
@image html chart_pie3.png
##############################################################
@example chart_doughnut.c
Example of creating an Excel Doughnut chart.
The default doughnut chart:
@image html chart_doughnut1.png
It is possible to define chart colors for most types of libxlsxwriter charts
via the series formatting functions. However, Pie/Doughnut charts are a
special case since each segment is represented as a point so it is necessary
to assign formatting to each point in the series.
Chart 4 shows how to set segment colors and other options.
@image html chart_doughnut2.png
##############################################################
@example chart_clustered.c
Example of creating a clustered Excel chart where there are two levels of
category on the X axis.
The categories in clustered charts are 2D ranges, instead of the more normal
1D ranges. The series are shown as formula strings for clarity but you can
also use the a list syntax.
@image html chart_clustered.png
##############################################################
@example chart_data_table.c
Example of creating charts with data tables.
Chart 1 in the following example is a column chart with default data table:
@image html chart_data_table1.png
Chart 2 is a column chart with default data table with legend keys:
@image html chart_data_table2.png
##############################################################
@example chart_data_tools.c
A demo of an various Excel chart data tools that are available via a
libxlsxwriter chart. These include Drop Lines and High-Low Lines.
Chart 1: chart with high-low lines.
@image html chart_data_tools5.png
Chart 2: chart with drop lines.
@image html chart_data_tools6.png
Chart 3: chart with up-down bars.
@image html chart_data_tools4.png
Chart 4: chart with formatted Up-down bars.
@image html chart_data_tools7.png
Chart 5: chart with markers and data labels.
@image html chart_data_tools8.png
Chart 6: chart with error bars.
@image html chart_data_tools3.png
Chart 7: chart with a trendline.
@image html chart_data_tools9.png
##############################################################
@example chart_data_labels.c
A demo of an various Excel chart data label features that are available via a
libxlsxwriter chart, including custom data labels.
Chart 1: chart with standard data labels.
@image html chart_data_labels11.png
Chart 2: chart with Category and Value data labels.
@image html chart_data_labels12.png
Chart 3: chart with data labels with a user defined font.
@image html chart_data_labels13.png
Chart 4: chart with data labels and formatting.
@image html chart_data_labels22.png
Chart 5: chart with custom string data labels.
@image html chart_data_labels14.png
Chart 6: chart with custom data labels referenced from worksheet cells.
@image html chart_data_labels15.png
Chart 7: chart with a mix of custom and default labels. The items initialized
with '{0}' and items without a custom label (points 5 and 6 which come after
NULL) will get the default value. We also set a font for the custom items as
an extra example.
@image html chart_data_labels16.png
Chart 8: chart with some deleted custom labels and defaults.
@image html chart_data_labels17.png
Chart 9: chart with custom string data labels and formatting.
@image html chart_data_labels23.png
##############################################################
@example chart_fonts.c
An example of creating a simple chart with different fonts.
@image html chart_fonts.png
##############################################################
@example chart_pattern.c
An example of creating a simple chart with different patterns.
@image html chart_pattern.png
##############################################################
@example chart_styles.c
An example showing all 48 default chart styles available in Excel 2007 using
the chart `chart_set_style()` method.
@image html chart_styles.png
##############################################################
@example chartsheet.c
An example of creating a simple bar chart in a chartsheet.
@image html chartsheet.png
+85
View File
@@ -0,0 +1,85 @@
/**
@page faq Frequently Asked Questions
@tableofcontents
The section outlines some answers to some frequently asked questions.
@section faq_template 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.
@section faq_formula_zero Q. Why do my formulas show a zero result in some, non-Excel applications?
Due to a wide range of possible formulas and the 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.
@code
worksheet_write_formula_num(worksheet, 0, 0, "=2 + 2", NULL, 4);
@endcode
@note LibreOffice doesn't recalculate Excel formulas that reference other
cells by default, in which case you will get the default XlsxWriter value of
0. You can work around this by setting the "LibreOffice Preferences ->
LibreOffice Calc -> Formula -> Recalculation on File Load" option to "Always
recalculate" (see the LibreOffice
[documentation](https://help.libreoffice.org/6.4/en-US/text/scalc/01/06080000.html?DbPAR=CALC)). Or,
you can set a blank string result in the formula, which will also force
recalculation:
@code
worksheet_write_formula_str(worksheet, 0, 0, "=Sheet1!$A$1", NULL, "");
@endcode
@section faq_range_format 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.
@section faq_msvc Q. Is Visual C++ on Windows supported?
Yes. See @ref gsg_vcpkg.
@section faq_features 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](https://xlsxwriter.readthedocs.io) module.
@section faq_autofit 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.
@section faq_faq Q. Do people actually ask these questions frequently, or at all?
Apart from this question, yes.
Next: @ref bugs
*/
@@ -0,0 +1,778 @@
/**
@page getting_started Getting Started with libxlsxwriter
@tableofcontents
Here are some instructions to get you up and running with the libxlsxwriter
library on different OSes.
@section gsg_quick_start Quick-start on Linux
If you prefer to assemble Ikea furniture first and only read the instructions
when you have parts left over then the following minimal set of commands
should get you up and running 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
If you read the instructions first and then assemble the furniture you will
know how to proceed.
@section gsg_linux Installation on Linux
@subsection gsg_dependencies Install the dependencies
The only non-optional dependency when building libxlsxwriter is [Zlib](http://www.zlib.net).
You can install `zlib` from source as follows:
curl -O -L http://www.zlib.net/zlib-1.2.11.tar.gz
tar zxf zlib-1.2.11.tar.gz
cd zlib-1.2.11
./configure
make
sudo make install
Alternatively, you can use your OS packager to install the `zlib` development
libraries. For example:
sudo apt-get install -y zlib1g-dev
The zlib version must be >= 1.2.8 to avoid compilation issues.
@note There are optional dependencies that can be installed for testing.
See @ref running_the_tests.
@subsection gsg_git Get the source code
To get the latest version of the source code you can clone the libxlsxwriter
repository from GitHub:
git clone https://github.com/jmcnamara/libxlsxwriter.git
Alternatively you can get a tarball of the latest source code as follows:
curl -O -L http://github.com/jmcnamara/libxlsxwriter/archive/master.tar.gz
@subsection gsg_build 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
To see a verbose summary of the compilation steps use `V=1`:
make V=1
With CMake you can build the library as follows:
cd cmake # Or another sub-directory.
cmake ..
cmake --build .
@subsection gsg_examples Build the examples
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:
# With Make:
make examples
# or CMake:
cd cmake
cmake .. -DBUILD_EXAMPLES=ON
cmake --build .
# Then:
./examples/hello
This will create a `hello_world.xlsx` file in your current directory. Open the
file in a spreadsheet application. The output should look like this: @image
html hello01.png
@subsection gsg_install Install the library
Libxlsxwriter supports a simplified installation scheme for a static and
dynamic/shared library and header files.
sudo make install
The files are installed to `/usr/local` by default but this can be overridden
by using the `PREFIX` environmental variable:
make install PREFIX=/usr/third_party
A staging directory can be set with `DESTDIR` which is prepended to all
install paths. This is a an occasionally useful feature for packaging:
make install PREFIX=/usr/third_party DESTDIR=./staging/
This would build and link the code with `/usr/third_party` as the
installation location but actually install to `./staging/usr/third_party`.
With CMake you can install the library as follows:
cd cmake
cmake ..
cmake --build . --target install
@subsection gsg_using Using the library
Using your source code editor create a file like the following called
`myexcel.c`:
@code
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("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 install commands in the previous section then you
should be able to compile the program as follows:
cc myexcel.c -o myexcel -lxlsxwriter
In some OS environments, or if you changed the `PREFIX` location, you may
have to provide explicit `include` and `lib` paths:
cc myexcel.c -o myexcel -I/usr/local/include -L/usr/local/lib -lxlsxwriter
You can also use
[pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/)
(after installation of the library) to automatically determine the required
arguments and paths:
$ pkg-config --cflags --libs xlsxwriter
-I/usr/local/include -L/usr/local/lib -lxlsxwriter -lz
You can add this information to your compilation as follows:
cc myexcel.c -o myexcel `pkg-config --cflags --libs xlsxwriter`
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
@section gsg_macos Installation on macOS and iOS
The easiest way to install libxlsxwriter for Xcode and iOS is to use the
CocoaPods method shown in the next section.
To install libxlsxwriter from the macOS commandline requires the
[Xcode "commandline tools"](https://developer.apple.com/xcode/resources/).
You can then follow the same instructions for compiling and installing on
Linux, as shown above.
For commandline access to libxlsxwriter you can also use
[brew/homebrew](https://brew.sh), see below.
@subsection gsg_cocoapods Install using CocoaPods for Xcode
For iOS and macOS projects in Xcode you can install libxlsxwriter using
[CocoaPods](https://cocoapods.org).
Add the following entry to your `Podfile`:
pod 'libxlsxwriter', '~> 0.9'
if you are using Swift, you can now add an import:
import xlsxwriter
And call its C functions like this:
let documentDirectory = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
let fileURL = documentDirectory.appendingPathComponent("hello_world.xlsx")
let workbook = workbook_new((fileURL.absoluteString.dropFirst(6) as NSString).fileSystemRepresentation)
let worksheet = workbook_add_worksheet(workbook, nil)
worksheet_write_string(worksheet, 0, 0, "Hello", nil)
worksheet_write_number(worksheet, 1, 0, 123, nil)
workbook_close(workbook)
For a sample Xcode project that uses the libxlsxwriter cocoapod for iOS and
macOS with Objective-C and Swift see [libxlsxwriter Cocoa
Examples](https://github.com/lrossi/libxlsxwriterCocoaExamples) or
[LibXlsxWriterSwiftSample](https://github.com/FrankenApps/LibXlsxWriterSwiftSample).
@subsection gsg_brew Installation on macOS with homebrew
On macOS you can also use [brew/homebrew](https://brew.sh):
brew install libxlsxwriter
Once installed you can compile and run a libxlsxwriter program as follows:
cc myexcel.c -o myexcel -I/usr/local/include -L/usr/local/lib -lxlsxwriter
./myexcel
@section gsg_windows Installation on Windows
There are several ways to compile libxlsxwriter on and for Windows, see below.
@subsection gsg_vcpkg Using vcpkg for Microsoft Visual Studio
The most convenient way to get the latest release version of libxlsxwriter and
integrate it into your Visual Studio build environment is to use the
[vcpkg](https://vcpkg.io) tool:
> vcpkg is a free C/C++ package manager for acquiring and managing
> libraries. Choose from over 1500 open source libraries to download and build
> in a single step or add your own private libraries to simplify your build
> process. Maintained by the Microsoft C++ team and open source contributors.
Install vcpkg and libxlsxwriter as follows in Windows CMD or Powershell:
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
bootstrap-vcpkg.bat
vcpkg install libxlsxwriter
You should then see libxlsxwriter installed as follows (note that the required
zlib dependency has also been installed):
vcpkg list
libxlsxwriter:x86-windows 0.8.6-1 Libxlsxwriter is a C library that ...
zlib:x86-windows 1.2.11-5 A compression library
You can also install libxlsxwriter for other build targets like `x64`
vcpkg install libxlsxwriter:x64-windows
vcpkg list
libxlsxwriter:x64-windows 1.1.4 Libxlsxwriter is a C library that ...
libxlsxwriter:x86-windows 1.1.4 Libxlsxwriter is a C library that ...
zlib:x64-windows 1.2.11#13 A compression library
zlib:x86-windows 1.2.11#13 A compression library
To use libxlsxwriter from within Visual Studio you can "integrate" it into
your environment:
vcpkg integrate install
Applied user-wide integration for this vcpkg root.
All MSBuild C projects can now include libxlsxwriter directly. Linking will
also be handled automatically. For example, create a new Win32 Console (or
other C/C++) application in Visual Studio:
File
-> New
-> Project
Visual C++
-> Win32
-> Win32 Console Application
Replace the empty main with a libxlsxwriter example from the distro. For
example:
@code
// Some older versions on Visual Studio may need "stdafx.h".
// #include "stdafx.h"
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("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;
}
@endcode
Change the target to "Release" and the architecture to "x86" or "x64"
(depending on the version you installed above). You can now "Build Solution".
The resulting executable will be put in the output directory with the required
"xlsxwriter.dll" and "zlib1.dll" files.
@subsection gsg_cmake_app Using CMake for Microsoft Visual Studio
For a more manual installation, and for older versions of Microsoft Visual
Studio or Windows, you can use CMake as shown below.
Open a Windows CMD or Command Window and set up your MSVC environment, if
required. Something like this:
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
# Or:
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
Then create a work directory and an install directory that the include and
library files will be installed to. Set the follow variables to point to the
directories:
set WORK_DIR=C:/Users/Username/tmp
set INSTALL_DIR=C:/Users/Username/tmp/install_dir
Build the Zlib library:
cd %WORK_DIR%
git clone https://github.com/madler/zlib.git
cd zlib
mkdir build
cd build
cmake .. -G "Visual Studio 14 Win64" -DCMAKE_INSTALL_PREFIX:PATH="%INSTALL_DIR%/zlib"
cmake --build . --config Release --target install
Build the libxlsxwriter library:
cd %WORK_DIR%
git clone https://github.com/jmcnamara/libxlsxwriter.git
cd libxlsxwriter
mkdir build
cd build
cmake .. -G "Visual Studio 14 Win64" -DCMAKE_INSTALL_PREFIX:PATH="%INSTALL_DIR%/libxlsxwriter" -DZLIB_ROOT:STRING="%INSTALL_DIR%/zlib"
cmake --build . --config Release --target install
Create a new Win32 Console (or other C/C++) application in Visual Studio:
File
-> New
-> Project
Visual C++
-> Win32
-> Win32 Console Application
Change the ARCH in the main Dialog to "x64" and the Configuration to "Release"
(or to match the parameters to cmake).
Replace the empty main with a libxlsxwriter example from the distro. Make sure
to include "stdafx.h" and "xlsxwriter.h":
@code
#include "stdafx.h" // This may not be required.
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("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;
}
@endcode
Edit the application properties:
Project
-> ConsoleApplication Properties
Set the libxlsxwriter include path to match the path used above:
Configuration Properties
-> C/C++
-> General
-> Additional Include Directories
Set it to the following (or similar path used above):
C:\Users\Username\tmp\install_dir\libxlsxwriter\include
Set the linker directories to match the path created above:
Configuration Properties
-> Linker
-> General
-> Additional Library Directories
Add the following (or similar paths used above):
C:\Users\Username\tmp\install_dir\libxlsxwriter\lib\x64\Release
C:\Users\Username\tmp\install_dir\zlib\lib
Set the linker additional libraries to match the zlib and xlsxwriter libs
created above:
Configuration Properties
-> Linker
-> Input
-> Additional Dependencies
Add the following:
xlsxwriter.lib
zlib.lib
Build the solution and run the output executable. It should create a
hello_world.xlsx file in the same directory you ran it from.
@subsection gsg_ming Installation on Windows using Mingw-w64 and MSYS2
The libxlsxwriter library can also be compiled on Windows using the
[Mingw-w64](http://mingw-w64.org/doku.php) "Minimalist GNU for Windows"
toolchain. These tools can be run from the Windows `cmd.exe` but it is
recommended to use the [MSYS2](http://msys2.github.io) "Minimal System" Bourne
Shell.
Here are some instructions on how to compile libxlsxwriter with Mingw-w64 and
MSYS2:
# Install MSYS2 64 or 32 bit from http://msys2.github.io/
# Install the dev tools for libxlsxwriter.
pacman -S git gcc make zlib-devel
# Clone and build libxlsxwriter.
git clone https://github.com/jmcnamara/libxlsxwriter.git
cd libxlsxwriter/
make
By default the library is installed in `/usr/local` on MinGW/MSYS systems. If
you know how to extend your build environments to use that directory then you
can just run `make install`. However, it is generally causes less compile/link
issues if you install them in the `/usr` directory like this:
make install PREFIX=/usr
After compilation you can follow the instructions in the @ref gsg_using
section above. When compiling with the library you may also need to link
against the zlib library using `-lz`:
gcc myexcel.c -o myexcel -lxlsxwriter -lz
It is also possible to use [Cygwin](https://cygwin.com) and the older [MinGW
and MSYS](http://mingw.org). Libxlsxwriter has been confirmed to compile and
work in all of these environments.
See also @ref gsg_tmpdir.
@subsection gsg_qt Installation in Qt-Creator for Windows
The following external guide shows how to [Build libxlsxwriter inside
Qt-Creator for Windows](https://github.com/jmcnamara/libxlsxwriter/issues/270)
with step by step instructions.
@section gsg_bsd Installation on FreeBSD and OpenBSD
Installation on FreeBSD and OpenBSD is mainly the same as on @ref gsg_linux
"Linux". To compile the library @ref gsg_git "get the source code" and build it
using **gmake** (not make):
cd libxlsxwriter
gmake
Then follow the instructions in the Linux section to @ref gsg_install
"install" and @ref gsg_using "use" the library.
Both FreeBSD and OpenBSD come with the zlib development libraries
pre-installed so there are no additional dependencies. However, if you have
any issues then follow the instructions to @ref gsg_dependencies "install zlib".
@section gsg_compilation_options Compilation Options
As shown in the previous sections Libxlsxwriter provides both a Make and
CMake based build system. The Make build is a straightforward system for
building the library and running tests on Unix like systems. The CMake system
offers support for more operating systems, cross compilation, and integration
with larger CMake builds. In particular it enables building on Windows.
The following are various compilation targets and options for both build systems:
| Make | CMake | Description |
| :----------------------- | :----------------------------------------- | :-------------------------------------------------------- |
| `examples` | `-DBUILD_EXAMPLES=ON` | Build the example |
| `test` | `-DBUILD_TESTS=ON` | Build the tests |
| `USE_DTOA_LIBRARY=1` | `-DUSE_DTOA_LIBRARY=ON` | Use alternative double in sprintf |
| `USE_MEM_FILE=1` | `-DUSE_MEM_FILE=ON` | Use `fmemopen()`/`open_memstream()` instead of temp files |
| `USE_OPENSSL_MD5=1` | `-DUSE_OPENSSL_MD5=ON` | Use OpenSSL for MD5 digest |
| `USE_NO_MD5=1` | `-DUSE_NO_MD5=ON` | Don't use a MD5 digest |
| `USE_SYSTEM_MINIZIP=1` | `-DUSE_SYSTEM_MINIZIP=ON` | Use system minzip library |
| `USE_STANDARD_TMPFILE=1` | `-DUSE_STANDARD_TMPFILE=ON` | Use system `tmpfile()` function |
| `USE_BIG_ENDIAN=1` | `-DUSE_BIG_ENDIAN=ON` | Build on big endian systems |
| `universal_binary` | `-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"` | Create a macOS "Universal Binary" |
| | `-DBUILD_SHARED_LIBS=ON` | Build shared library (default on) |
| | `-DUSE_STATIC_MSVC_RUNTIME=ON` | Use static msvc runtime library |
| | `-DCMAKE_BUILD_TYPE=Release` | Set the build type. |
The compilation options would be used as follows:
# Make
make examples USE_DTOA_LIBRARY=1
# CMake
cd cmake
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=ON -DUSE_DTOA_LIBRARY=ON
cmake --build . --config Release
Each of the options are explained below:
- `examples/BUILD_EXAMPLES`: Builds the @ref examples "example programs".
- `test/BUILD_TESTS`: Builds the tests (see @ref running_the_tests). With Make
the tests are also run once they are compiled. With CMake you can run them
using `ctest`.
- `USE_DTOA_LIBRARY`: See @ref gsg_dtoa "using a double formatting library".
- `USE_MEM_FILE`: Use fmemopen()/open_memstream() instead of temporary files.
This option isn't on by default since it isn't supported on Windows.
- `USE_OPENSSL_MD5`: Uses OpenSSL to provide a MD5 digest of image files in
order to avoid storing duplicates. See @ref gsg_md5.
- `USE_NO_MD5`: Don't use a MD5 digest of image files in order to remove
duplicates. This can be used if you aren't handling image files and don't
need the additional function in the library. See @ref gsg_md5.
- `USE_SYSTEM_MINIZIP`: Uses a system minizip library, rather than the
included copy, to create the xlsx zip container. See @ref gsg_minizip.
- `USE_STANDARD_TMPFILE`: Uses the standard library `tmpfile()` function
to handle temp files instead of `tmpfileplus`. See @ref gsg_tmpdir.
- `USE_BIG_ENDIAN`: Compiles libxlsxwriter on a big endian system. See @ref
gsg_endian.
- `universal_binary/CMAKE_OSX_ARCHITECTURES`: Builds a "universal binary" for
both Apple silicon and Intel-based Macs. See @ref gsg_universal.
- `BUILD_SHARED_LIBS`: Builds a dynamically loading version of the library
(`.so`, `.dll` or `.dylib` depending on the operating system).
- `USE_STATIC_MSVC_RUNTIME`: Sets flags for Microsoft Visual C to use a static
MSVC runtime.
- `CMAKE_BUILD_TYPE`: Sets the build type (generally `Release` or `Debug`).
You can view, and set, your CMake options from within your build directory
using the `ccmake` tool:
ccmake .
@subsection gsg_dtoa Using a double formatting library
Excel uses an IEEE 754 doubles for all numeric values. These values are stored
in standard `sprintf(...,"%.16G",...)` formatting as numbers like "1234.56" or
"456E+123". However in some locales, such as "de_DE" these numbers can be
stored with the locale specific decimal place like "1234,56" which causes
Excel to give an error when it loads the file.
It some cases this issue can be resolved by using the `setlocale()` or
`uselocale()` functions in your application. Alternatively you can compile
libxlsxwriter with support for a third party `dtoa()` (decimal to ascii)
function. Currently libxlsxwriter uses the [Milo Yip DTOA
library](https://github.com/miloyip/dtoa-benchmark) as an optional
compilation. This avoids the locale sprintf issue and it is also 40-50% faster
than the standard dtoa for raw numeric data.
@subsection gsg_md5 MD5 functionality for handling duplicate images
Libxlsxwriter uses a an MD5 digest to avoid including duplicate image files in
the xlsx file. By default it uses a third party library, [Openwall
MD5](https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5),
which is a fast portable implementation of the MD5 Algorithm and which uses
the same function prototypes as OpenSSL MD5 digest. See @ref license.
The Openwall MD5 code is included in the libxlsxwriter repo and compiled in by
default. If you don't want to use this code, and the additional license, you
can use OpenSSL's MD5 functions dynamically by using the `USE_OPENSSL_MD5`
option:
make USE_OPENSSL_MD5=1
# or:
cmake .. -DUSE_OPENSSL_MD5=ON
This requires that you have the OpenSSL development libraries installed and on
paths known to your compiler.
If this MD5 functionality isn't required it is possible to compile
libxlsxwriter without image de-duplication by using the `USE_NO_MD5=1` option:
make USE_NO_MD5=1
# or:
cmake .. -DUSE_NO_MD5=ON
@subsection gsg_minizip Linking against system minizip
Libxlsxwriter uses the `minizip` component of [Zlib](http://www.zlib.net) to
create the xlsx zip file container. The source files for `minizip` are
included in the src tree of libxlsxwriter and are statically linked by
default.
If you have a `lminizip` library already installed on your system and prefer
to dynamically link against that you can use the following compilation option:
make USE_SYSTEM_MINIZIP=1
# or:
cmake .. -DUSE_SYSTEM_MINIZIP=ON
@subsection gsg_tmpdir Specifying a TEMP directory for libxlsxwriter
The libxlsxwriter library creates temporary files in the system `TEMP`
directory during assembly of an xlsx file. On Windows this directory may not
be writeable by a libxlsxwriter application (although it will try several
`TEMP` locations before returning an error). To work around this you can set
the `tmpdir` parameter of the #lxw_workbook_options struct and pass it to
`workbook_new_opt()`:
@code
lxw_workbook_options options = {.constant_memory = LXW_FALSE,
.tmpdir = "C:\\Temp"};
lxw_workbook *workbook = workbook_new_opt("filename.xlsx", &options);
@endcode
This can also be used on Unix systems where the `TEMP` directory isn't
writeable.
The TEMP file handling with optional temporary directory support is provided
by the
[Tmpfileplus](http://www.di-mgt.com.au/c_function_to_create_temp_file.html)
library which is included in the source tree. If you wish to use the standard
library `tmpfile()` function instead you can compile without `tmpfileplus` as
follows:
make USE_STANDARD_TMPFILE=1
# or:
cmake .. -DUSE_STANDARD_TMPFILE=ON
@note When using the the standard library `tmpfile()` the `tmpdir` parameter,
shown above, is ignored.
@subsection gsg_endian Compiling on Big Endian Architecture
Libxlsxwriter can be compiled on a big endian system as follows:
make USE_BIG_ENDIAN=1
# or:
cmake .. -DUSE_BIG_ENDIAN=ON
@subsection gsg_universal Compiling a universal binary on macOS
With Xcode 12.2 and later you can compile libxlsxwriter as a "universal
binary" for both Apple silicon and Intel-based Macs, i.e., arm64 and x86_64.
You can compile a universal binary with standard make as follows:
$ make universal_binary
# Which gives:
$ lipo -archs lib/libxlsxwriter.a
x86_64 arm64
$ lipo -archs lib/libxlsxwriter.dylib
x86_64 arm64
Or with CMake:
cd cmake
cmake .. -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
make
@subsection gsg_minimal Minimal dependency compilation
As explained in the previous sections Libxlsxwriter includes 3 additional
libraries within the `third_party` directory:
1. `md5`: Used for MD5 hashing to avoid including duplicate images. See @ref
gsg_md5.
2. `minizip`: Uses creating the xlsx zip container (this is part of the zlib
code base but generally packaged separately). See @ref gsg_minizip.
3. `tmpfileplus`: Used mainly to overcome temp file issues on Windows but also
used for changing the default temp directory. See @ref gsg_tmpdir.
These components are included in the libxlsxwriter repository to ensure that
the library compiles and runs on as many OSes as possible with the least
amount of additional dependencies.
However, all of these are optional and a minimal version of libxlsxwriter can
be compiled without them by relying on external libraries as follows:
# Make:
make USE_OPENSSL_MD5=1 USE_SYSTEM_MINIZIP=1 USE_STANDARD_TMPFILE=1
# CMake:
cd cmake
cmake .. -DUSE_OPENSSL_MD5=ON -DUSE_SYSTEM_MINIZIP=ON -DUSE_STANDARD_TMPFILE=ON
cmake --build .
@section gsg_next Next steps
Once you get libxlsxwriter built and working the next sections will show you
how to create some more in-depth examples.
Next: @ref tutorial01
*/
@@ -0,0 +1,30 @@
/**
@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, formulas and hyperlinks 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](https://xlsxwriter.readthedocs.io) module
by the same author and is licensed under a FreeBSD @ref license.
Next: @ref getting_started
*/
+78
View File
@@ -0,0 +1,78 @@
/**
@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, formulas
and hyperlinks to multiple worksheets in an Excel 2007+ XLSX file. It supports
features such as:
- 100% compatible Excel XLSX files.
- Full Excel formatting.
- Merged cells.
- Defined names.
- Autofilters.
- Charts.
- Data validation and drop down lists.
- Conditional formatting.
- Worksheet PNG/JPEG/GIF images.
- Cell comments.
- Support for adding Macros.
- Memory optimization mode for writing large files.
- Source code available on [GitHub](https://github.com/jmcnamara/libxlsxwriter).
- FreeBSD @ref license.
- ANSI C.
- Works with GCC, Clang, Xcode, MSVC 2015, ICC, TCC, MinGW, MingGW-w64/32.
- Works on Linux, FreeBSD, OpenBSD, OS X, iOS and Windows. Also works on MSYS/MSYS2 and Cygwin.
- Compiles for 32 and 64 bit.
- Compiles and works on big and little endian systems.
- 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 chart.h "The Chart object"
- @ref chartsheet.h "The Chartsheet object"
- @ref utility.h "Utility functions and macros"
- @ref working_with_formats
- @ref working_with_colors
- @ref working_with_formulas
- @ref working_with_dates
- @ref working_with_charts
- @ref working_with_object_positioning
- @ref working_with_autofilters
- @ref working_with_data_validation
- @ref working_with_conditional_formatting
- @ref working_with_tables
- @ref working_with_comments
- @ref working_with_outlines
- @ref working_with_memory
- @ref working_with_macros
- @ref examples
- @ref running_the_tests
- @ref faq
- @ref bugs
- @ref author
- @ref license
- @ref changes
*/
@@ -0,0 +1,111 @@
/**
@page running_the_tests Running the Test Suite
@tableofcontents
This section shows how to set up and run the test suite for libxlsxwriter.
@section tests_functional 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 pip install pytest
The functional tests can then be run:
$ cd libxlsxwriter
$ make test_functional
=========================== test session starts ===========================
collected 749 items
test/functional/test_array_formula.py::TestCompareXLSXFiles::test_array_formula01 PASSED [ 0%]
test/functional/test_array_formula.py::TestCompareXLSXFiles::test_array_formula02 PASSED [ 0%]
test/functional/test_array_formula.py::TestCompareXLSXFiles::test_array_formula03 PASSED [ 0%]
test/functional/test_array_formula.py::TestCompareXLSXFiles::test_array_formula04 PASSED [ 1%]
test/functional/test_autofilter.py::TestCompareXLSXFiles::test_autofilter00 PASSED [ 1%]
test/functional/test_autofilter.py::TestCompareXLSXFiles::test_autofilter01 PASSED [ 1%]
...
test/functional/test_write_data.py::TestCompareXLSXFiles::test_data05 PASSED [ 99%]
test/functional/test_write_data.py::TestCompareXLSXFiles::test_data06 PASSED [ 99%]
test/functional/test_write_data.py::TestCompareXLSXFiles::test_data07 PASSED [ 99%]
test/functional/test_write_data.py::TestCompareXLSXFiles::test_data08 PASSED [ 99%]
test/functional/test_write_data.py::TestCompareXLSXFiles::test_data09 PASSED [100%]
=========================== 749 passed in 30.60s ===============================
@section tests_ Unit Tests
The unit tests test the components of the library at the level of individual
functions or compilation units.
The unit tests uses the [ctest](http://github.com/bvdberg/ctest) test
framework. This is included as a header file in the `test/unit` directory
and doesn't need to be installed.
The unit tests can then be run as follows:
$ make test_unit
Compiling unit tests ...
TEST 1/429 utility:lxw_col_to_name [OK]
TEST 2/429 utility:test_datetime_date_and_time [OK]
TEST 3/429 utility:test_datetime_date_only [OK]
TEST 4/429 utility:test_datetime_date_only_1904 [OK]
TEST 5/429 utility:test_datetime_time_only [OK]
TEST 6/429 utility:test_unixtime [OK]
...
TEST 425/429 worksheet:worksheet_table12 [OK]
TEST 426/429 worksheet:worksheet_table13 [OK]
TEST 427/429 worksheet:worksheet_table14 [OK]
TEST 428/429 worksheet:worksheet_table15 [OK]
TEST 429/429 table:xml_declaration [OK]
RESULTS: 429 tests (429 ok, 0 failed, 0 skipped) ran in 153 ms
Both functional and unit test can be run together:
$ make test
@section tests_cmake Testing with CMake
You can run the unit and functional tests via CMake as follows:
cd cmake
cmake .. -DBUILD_TESTS=ON
cmake --build .
ctest -V
@section tests_valgrind 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
@section tests_ci GitHub Actions Continuous Integration
Libxlsxwriter is configured to run all these tests with [GitHub Actions
Continuous Integration](https://github.com/jmcnamara/libxlsxwriter/actions)
for each commit.
Next: @ref faq
*/
+113
View File
@@ -0,0 +1,113 @@
/**
@page tutorial01 Tutorial 1: Create a simple XLSX file
Next: @ref tutorial02.
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 initialize 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 workbook_new() function which takes the filename
that we want to create:
@dontinclude tutorial1.c
@skipline workbook_new
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.
*/
+55
View File
@@ -0,0 +1,55 @@
/**
@page tutorial02 Tutorial 2: Adding formatting to the XLSX File
Next: @ref tutorial03.
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
View 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"
*/
@@ -0,0 +1,217 @@
/**
@page working_with_autofilters Working with Autofilters
@tableofcontents
An autofilter in Excel is a way of filtering a 2D range of data based on some
simple criteria.
@image html autofilter1.png
@section ww_autofilters_range Applying an autofilter
The first step is to apply an autofilter to a cell range in a worksheet using
the worksheet_autofilter() function:
@code
worksheet_autofilter(worksheet, 0, 0, 10, 3);
@endcode
Or more explicitly using the RANGE() macro:
@code
worksheet_autofilter(worksheet, RANGE("A1:D11")); //Same as above.
@endcode
@section ww_autofilters_data Filtering data in an autofilter
The `worksheet_autofilter()` function defines the cell range that the filter
applies to and creates drop-down selectors in the header row.
However, in order to apply a filter condition it is necessary to add filter
rules to the columns using the `%worksheet_filter_column()`,
`%worksheet_filter_column2()` or `%worksheet_filter_list()` functions:
- `worksheet_filter_column()`: filter on a single criterion such as "Column ==
East". More complex conditions such as "<=" or ">=" can also be used.
- `worksheet_filter_column2()`: filter on two criteria such as "Column == East
or Column == West". Complex conditions can also be used.
- `worksheet_filter_list()`: filter on a list of values such as "Column in (East, West,
North)".
For example you could create a filter like "Column A == East" using a
lxw_filter_rule rule and the `worksheet_filter_column()` function like this:
@code
lxw_filter_rule filter_rule = {.criteria = LXW_FILTER_CRITERIA_EQUAL_TO,
.value_string = "East"};
worksheet_filter_column(worksheet, 0, &filter_rule);
@endcode
Unfortunately, it isn't sufficient to just specify the filter condition. You
must also hide the rows that don't match the criteria since Excel doesn't do
that automatically when reading a file. With libxlsxwriter you can hide rows
using the `worksheet_set_row_opt()` function with the lxw_row_col_options
`hidden` parameter.
The following is an example of how you might filter a data range to match an
autofilter criteria:
@code
lxw_row_col_options hidden = {.hidden = LXW_TRUE};
lxw_filter_rule filter_rule = {.criteria = LXW_FILTER_CRITERIA_EQUAL_TO,
.value_string = "East"};
worksheet_filter_column(worksheet, 0, &filter_rule);
for (i = 0; i < 100; i++) {
// Write some other cell data for a row...
if (strcmp(data[i].region, "East") == 0) {
// Row matches the filter, no further action required.
}
else {
// Hide rows that don't match the filter.
worksheet_set_row_opt(worksheet, i + 1, LXW_DEF_ROW_HEIGHT, NULL, &hidden);
}
}
@endcode
Note, the `if()` statement above is written to match the logic of the criteria
in the rule. However you could get the same results with the following
simpler, but reversed, logic:
@code
if (strcmp(data[i].region, "East") != 0) {
worksheet_set_row_opt(worksheet, i + 1, LXW_DEF_ROW_HEIGHT, NULL, &hidden);
}
@endcode
@section ww_autofilters_criteria Setting a filter criteria for a column
The `worksheet_filter_column()` and `worksheet_filter_column2()` functions can
be used to filter columns in a autofilter range based on simple conditions:
@code
lxw_filter_rule filter_rule1 = {.criteria = LXW_FILTER_CRITERIA_EQUAL_TO,
.value_string = "East"};
lxw_filter_rule filter_rule2 = {.criteria = LXW_FILTER_CRITERIA_GREATER_THAN,
.value = 3000};
lxw_filter_rule filter_rule3 = {.criteria = LXW_FILTER_CRITERIA_LESS_THAN,
.value = 8000};
worksheet_filter_column (worksheet, 0, &filter_rule1);
worksheet_filter_column2(worksheet, 2, &filter_rule2, &filter_rule3, LXW_FILTER_AND);
@endcode
The `col` parameter, used in both these functions, is a zero indexed column
number and must refer to a column in an existing autofilter created with
`worksheet_autofilter()`.
The `criteria` parameter in lxw_filter_rule can have one of the following values:
- #LXW_FILTER_CRITERIA_EQUAL_TO: Filter cells equal to a value.
- #LXW_FILTER_CRITERIA_NOT_EQUAL_TO: Filter cells not equal to a value.
- #LXW_FILTER_CRITERIA_GREATER_THAN: Filter cells greater than a value.
- #LXW_FILTER_CRITERIA_LESS_THAN: Filter cells less than a value.
- #LXW_FILTER_CRITERIA_GREATER_THAN_OR_EQUAL_TO: Filter cells greater than or
equal to a value.
- #LXW_FILTER_CRITERIA_LESS_THAN_OR_EQUAL_TO: Filter cells less than or equal
to a value.
- #LXW_FILTER_CRITERIA_BLANKS: Filter cells that are blank. This does not
require a `.value_string` or `.value` value.
- #LXW_FILTER_CRITERIA_NON_BLANKS: Filter cells that are not blank. This does
not require a `.value_string` or `.value` value.
The `value` parameter is used to set a numeric matching condition while
`value_string` is used to set a string matching condition. Excel also allows
some simple string matching operations:
@code
// Begins with c.
lxw_filter_rule filter_rule1 = {.criteria = LXW_FILTER_CRITERIA_EQUAL_TO,
.value_string = "c*"};
// Doesn't begin with c.
lxw_filter_rule filter_rule2 = {.criteria = LXW_FILTER_CRITERIA_NOT_EQUAL_TO,
.value_string = "c*"};
// Ends with c.
lxw_filter_rule filter_rule3 = {.criteria = LXW_FILTER_CRITERIA_EQUAL_TO,
.value_string = "*c"};
// Doesn't end with c.
lxw_filter_rule filter_rule4 = {.criteria = LXW_FILTER_CRITERIA_NOT_EQUAL_TO,
.value_string = "*c"};
// Contains c.
lxw_filter_rule filter_rule5 = {.criteria = LXW_FILTER_CRITERIA_EQUAL_TO,
.value_string = "*c*"};
// Doesn't contain c.
lxw_filter_rule filter_rule6 = {.criteria = LXW_FILTER_CRITERIA_NOT_EQUAL_TO,
.value_string = "*c*"};
@endcode
You can use "*" to match any character or number and "?" to match any single
character or number. No other regular expression quantifier is supported by
Excel's filters. Excel's regular expression characters can be escaped using
"~".
@section ww_autofilters_list Setting a column list filter
Prior to Excel 2007 it was only possible to have either 1 or 2 filter
conditions such as the ones shown above with the `worksheet_filter_column()`
and `worksheet_filter_column()` functions.
Excel 2007 introduced a new list style filter where it is possible to specify one
or more "or" style criteria. For example if your column contained data for the
months of the year you could filter the data based on certain months:
@image html autofilter2.png
The `worksheet_filter_list()` function can be used to represent these types of
filters:
@code
char* list[] = {"March", "April", "May", NULL};
worksheet_filter_list(worksheet, 0, list);
@endcode
To filter blanks as part of the list use `Blanks` as a list item:
@code
char* list[] = {"March", "April", "May", "Blanks", NULL};
worksheet_filter_list(worksheet, 0, list);
@endcode
As explained above, it isn't sufficient to just specify filters. You must also
hide any rows that don't match the filter condition.
@section ww_autofilters_example Example
For a detailed working example with several different filter types see @ref
autofilter.c.
Next: @ref working_with_data_validation
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,46 @@
/**
@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 | `0x1000000` (note)
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`
@note Black in Html is actually `0x000000` but `#LXW_COLOR_BLACK` is defined
as 0x1000000 to avoid confusion with an undefined or Zero color value. It is
converted to the correct Html code internally.
Next: @ref working_with_formulas
*/
@@ -0,0 +1,283 @@
/**
@page working_with_comments Working with Cell Comments
Cell comments are a way of adding notation to cells in Excel. For example:
@code
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("comments1.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
worksheet_write_string( worksheet, 0, 0, "Hello" , NULL);
worksheet_write_comment(worksheet, 0, 0, "This is a comment");
return workbook_close(workbook);
}
@endcode
@image html comments1.png
@section ww_comments_properties Setting Comment Properties
The properties of the cell comment can be modified by passing an optional
#lxw_comment_options struct to `worksheet_write_comment_opt()` control the
format of the comment. For example:
@code
lxw_comment_options options = {.x_scale = 1.2, .y_scale = 0.5};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options);
@endcode
The following options are available in #lxw_comment_options:
- `author`
- `visible`
- `width`
- `height`
- `x_scale`
- `y_scale`
- `color`
- `font_name`
- `font_size`
- `start_row`
- `start_col`
- `x_offset`
- `y_offset`
The options are explained in detail below and shown in @ref comments2.c.
@subsection ww_comments_author Cell comments: author
This `author` option is used to indicate who is the author of the cell
comment. Excel displays the author of the comment in the status bar at the
bottom of the worksheet. This is usually of interest in corporate environments
where several people might review and provide comments to a workbook:
@code
lxw_comment_options options = {.author = "Ian McEwan"};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Atonement", &options);
@endcode
The default author for all cell comments in a worksheet can be set using
the `worksheet_set_comments_author()` function:
@code
worksheet_set_comments_author(worksheet, "Jane Gloriana Villanueva")
@endcode
@subsection ww_comments_visible Cell comments: visible
The `visible` option is used to make a cell comment visible when the worksheet
is opened. The default behavior in Excel is that comments are initially
hidden. However, it is also possible in Excel to make individual comments or
all comments visible. In libxlsxwriter individual comments can be made visible as
follows:
@code
lxw_comment_options options = {.visible = LXW_COMMENT_DISPLAY_VISIBLE};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello.", &options);
@endcode
The `visible` property should be set with one of the enum values from
#lxw_comment_display_types.
It is possible to make all comments in a worksheet visible using the
`worksheet_show_comments()` worksheet function. Alternatively, if all of the
cell comments have been made visible you can hide individual comments:
@code
lxw_comment_options options = {.visible = LXW_COMMENT_DISPLAY_HIDDEN};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options);
@endcode
@subsection ww_comments_width Cell comments: width
The `width` option is used to set the width of the cell comment box explicitly
in pixels:
@code
lxw_comment_options options = {.width = 200};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options);
@endcode
The width and height can be adjusted together:
@code
lxw_comment_options options = {.width = 200, .height = 50};
@endcode
@subsection ww_comments_height Cell comments: height
The `height` option is used to set the height of the cell comment box
explicitly in pixels:
@code
lxw_comment_options options = {.height = 50};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options);
@endcode
The width and height can be adjusted together:
@code
lxw_comment_options options = {.width = 200, .height = 50};
@endcode
@subsection ww_comments_x_scale Cell comments: x_scale
The `x_scale` option is used to set the width of the cell comment box
as a factor of the default width:
@code
lxw_comment_options options = {.x_scale = 2.0};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options);
@endcode
@subsection ww_comments_y_scale Cell comments: y_scale
The `y_scale` option is used to set the height of the cell comment box
as a factor of the default height:
@code
lxw_comment_options options = {.y_scale = 2.0};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options);
@endcode
@subsection ww_comments_color Cell comments: color
The `color` option is used to set the background color of cell comment
box. The color should be an RGB integer value, see @ref
working_with_colors.
@code
lxw_comment_options options1 = {.color = LXW_COLOR_GREEN};
lxw_comment_options options2 = {.color = 0xFF6600};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options1);
worksheet_write_comment_opt(worksheet, CELL("C7"), "Hello", &options2);
@endcode
@subsection ww_comments_font_name Cell comments: font_name
The `font_name` option is used to set the font for the comment:
@code
lxw_comment_options options = {.font_name = "Courier"};
@endcode
The default font is 'Tahoma'.
@subsection ww_comments_font_size Cell comments: font_size
The `font_size` option is used to set the font size for the comment:
@code
lxw_comment_options options = {.font_name = "Courier", .font_size = 10};
@endcode
The default font size is 8.
@subsection ww_comments_start_row Cell comments: start_row
The `start_row` option is used to set the row in which the comment will
appear. By default Excel displays comments one cell to the right and one cell
above the cell to which the comment relates. The row is zero indexed:
@code
lxw_comment_options options = {.start_row = 3, .start_col = 4};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options);
@endcode
See @ref ww_comments_notes
@subsection ww_comments_start_col Cell comments: start_col
The `start_col` option is used to set the column in which the comment will
appear. By default Excel displays comments one cell to the right and one cell
above the cell to which the comment relates. The column is zero indexed:
@code
lxw_comment_options options = {.start_row = 3, .start_col = 4};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options);
@endcode
See @ref ww_comments_notes
@subsection ww_comments_x_offset Cell comments: x_offset
The `x_offset` option is used to change the x offset, in pixels, of a
comment within a cell:
@code
lxw_comment_options options = {.x_offset = 30, .y_offset = 12};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options);
@endcode
See @ref ww_comments_notes
@subsection ww_comments_y_offset Cell comments: y_offset
The `y_offset` option is used to change the y offset, in pixels, of a
comment within a cell:
@code
lxw_comment_options options = {.x_offset = 30, .y_offset = 12};
worksheet_write_comment_opt(worksheet, CELL("C6"), "Hello", &options);
@endcode
See @ref ww_comments_notes
@subsection ww_comments_notes Notes on scaling of cell comments
<b>Note on options that move a cell position:</b>
Excel only displays offset cell comments when they are displayed as
`visible`. Excel does **not** display hidden cells as displaced when you mouse
over them. Please note this when using options that adjust the position of the
cell comment such as `start_row`, `start_col`, `x_offset` and `y_offset`.
<b>Note on row height and comments:</b>
If you specify the height of a row that contains a comment then libxlsxwriter
will adjust the height of the comment to maintain the default or user
specified dimensions. However, the height of a row can also be adjusted
automatically by Excel if the text wrap property is set or large fonts are
used in the cell. This means that the height of the row is unknown to the
library at run time and thus the comment box is stretched with the row. Use
the `worksheet_set_row()` function to specify the row height explicitly and
avoid this problem. See Example 8 of @ref comments2.c.
Next: @ref working_with_memory
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,503 @@
/**
@page working_with_data_validation Working with Data Validation
@tableofcontents
Data validation is a feature of Excel which allows restrictions to be placed
on the data that a user enters in a cell and to display associated help and
warning messages. It can also be used to restrict input to values in a drop
down list.
A typical use case might be to restrict data in a cell to integer values in a
certain range, to provide a help message to indicate the required value and to
issue a warning if the input data doesn't meet the stated criteria. In
`libxlsxwriter` this can be done as follows:
@code
lxw_data_validation *data_validation = calloc(1, sizeof(lxw_data_validation));
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
data_validation->minimum_number = 1;
data_validation->maximum_number = 10;
worksheet_data_validation_cell(worksheet, CELL("B3"), data_validation);
@endcode
@image html data_validate1.png
If the user inputs a value that doesn't match the specified criteria an error
message is displayed:
@image html data_validate4.png
For more information on data validation see the Microsoft support article
[Description and examples of data validation in Excel](http://support.microsoft.com/kb/211485).
The following sections describe how to use the
`worksheet_data_validation_cell()` and `worksheet_data_validation_range()`
functions and the various options of #lxw_data_validation.
@section ww_data_validate_functions The data validation functions
The `worksheet_data_validation_cell()` and `worksheet_data_validation_range()`
functions are used to construct an Excel data validation.
The data validation can be applied to a single cell or a range of cells:
@code
worksheet_data_validation_cell( worksheet, 2, 1, data_validation);
worksheet_data_validation_range(worksheet, 2, 1, 4, 1, data_validation);
// Same as above using the CELL() and RANGE() macros.
worksheet_data_validation_cell( worksheet, CELL("B3"), data_validation);
worksheet_data_validation_range(worksheet, RANGE("B3:B5"), data_validation);
@endcode
The lxw_data_validation struct used in these functions is explained below.
@section ww_data_validate_struct The lxw_data_validation struct
The lxw_data_validation struct is used to set the properties of a data
validation. A typical usage would look something like this:
@code
lxw_data_validation *data_validation = calloc(1, sizeof(lxw_data_validation));
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_GREATER_THAN;
data_validation->value_number = 10;
data_validation->show_input = LXW_VALIDATION_OFF;
@endcode
This example shows the main properties of lxw_data_validation and Excel data
validations:
- `validate`: The type of data to restrict the validation to. In this case it
is whole numbers.
- `criteria`: The criteria by which the data will be evaluated. In this case
whether the input is greater than a value.
- `value`: The value that the criteria applies to. This has several different
versions for different types of data. This could also be a `minimum` and
`maximum` value if the criteria used is a "BETWEEN" criteria. This is
explained in the @ref ww_data_validate_value section below.
- Other options such as `show_input` or `input_message`. These parameters are
explained in the @ref ww_data_validate_options section.
Note, in the examples in this document the `data_validation` variable is shown
as dynamically allocated, however an address of a static or automatic variable
could also be used. In these cases make sure that the struct members are
initialized to zero before setting other parameters.
@subsection ww_data_validate_validate validate
The `validate` parameter is used to set the type of data that you wish to
validate:
@code
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
@endcode
It is always required and it has no default value. In Excel the validate
parameters are:
- Whole
- Decimal
- List
- Date
- Time
- Text Length
- Custom
- Any
The equivalent parameters in libxlsxwriter are defined in
#lxw_validation_types:
- #LXW_VALIDATION_TYPE_INTEGER: Restrict cell input to whole/integer numbers
only.
- #LXW_VALIDATION_TYPE_INTEGER_FORMULA: Restrict cell input to whole/integer
numbers only, using a cell reference.
- #LXW_VALIDATION_TYPE_DECIMAL: Restrict cell input to decimal numbers only.
- #LXW_VALIDATION_TYPE_DECIMAL_FORMULA: Restrict cell input to decimal
numbers only, using a cell reference.
- #LXW_VALIDATION_TYPE_LIST: Restrict cell input to a list of strings in a
dropdown.
- #LXW_VALIDATION_TYPE_LIST_FORMULA: Restrict cell input to a list of strings
in a dropdown, using a cell range.
- #LXW_VALIDATION_TYPE_DATE: Restrict cell input to date values only, using a
lxw_datetime type.
- #LXW_VALIDATION_TYPE_DATE_FORMULA: Restrict cell input to date values only,
using a cell reference.
- #LXW_VALIDATION_TYPE_TIME: Restrict cell input to time values only, using a
lxw_datetime type.
- #LXW_VALIDATION_TYPE_TIME_FORMULA: Restrict cell input to time values only,
using a cell reference.
- #LXW_VALIDATION_TYPE_LENGTH: Restrict cell input to strings of defined
length, using a cell reference.
- #LXW_VALIDATION_TYPE_LENGTH_FORMULA: Restrict cell input to strings of
defined length, using a cell reference.
- #LXW_VALIDATION_TYPE_CUSTOM_FORMULA: Restrict cell to input controlled by a
custom formula that returns `TRUE/FALSE`.
- #LXW_VALIDATION_TYPE_ANY: Allow any type of input. Mainly only useful for
pop-up messages.
@subsection ww_data_validate_criteria criteria
The `criteria` parameter is used to set the criteria by which the data in the
cell is validated. It is almost always required except for the `list`,
`custom` and `any` validate options. It has no default value:
@code
data_validation->criteria = LXW_VALIDATION_CRITERIA_GREATER_THAN;
@endcode
Allowable values are defined in #lxw_validation_criteria:
- #LXW_VALIDATION_CRITERIA_BETWEEN: Select data between two values.
- #LXW_VALIDATION_CRITERIA_NOT_BETWEEN: Select data that is not between two values.
- #LXW_VALIDATION_CRITERIA_EQUAL_TO: Select data equal to a value.
- #LXW_VALIDATION_CRITERIA_NOT_EQUAL_TO: Select data not equal to a value.
- #LXW_VALIDATION_CRITERIA_GREATER_THAN: Select data greater than a value.
- #LXW_VALIDATION_CRITERIA_LESS_THAN: Select data less than a value.
- #LXW_VALIDATION_CRITERIA_GREATER_THAN_OR_EQUAL_TO: Select data greater than or equal to a value.
- #LXW_VALIDATION_CRITERIA_LESS_THAN_OR_EQUAL_TO: Select data less than or equal to a value.
The `list`, `custom` and `any` validate options don't require a
`criteria`. If you specify one it will be ignored.
@subsection ww_data_validate_value value, minimum, maximum
The `value` parameters are used to set the limiting value to which the
`criteria` is applied. It is always required and it has no default
value. There are different types of `value` parameter associated with
different types of data. They are:
`value_number`:
The `value_number` parameter is used to set the limiting value
to which the criteria is applied using a whole or decimal number. It is
typically used with #LXW_VALIDATION_TYPE_INTEGER and
#LXW_VALIDATION_TYPE_DECIMAL and #LXW_VALIDATION_TYPE_LENGTH.
@code
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_GREATER_THAN;
data_validation->value_number = 0;
data_validation->validate = LXW_VALIDATION_TYPE_DECIMAL;
data_validation->criteria = LXW_VALIDATION_CRITERIA_GREATER_THAN;
data_validation->value_number = 10.5;
data_validation->validate = LXW_VALIDATION_TYPE_LENGTH;
data_validation->criteria = LXW_VALIDATION_CRITERIA_GREATER_THAN;
data_validation->value_number = 3;
@endcode
`value_formula`:
The `value_formula` parameter is used to set the limiting value to which the
criteria is applied using a cell reference. It is valid for any of the
#lxw_validation_types types that end in `_FORMULA`:
@code
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER_FORMULA;
data_validation->criteria = LXW_VALIDATION_CRITERIA_GREATER_THAN;
data_validation->value_formula = "=E3";
data_validation->validate = LXW_VALIDATION_TYPE_TIME_FORMULA;
data_validation->criteria = LXW_VALIDATION_CRITERIA_EQUAL;
data_validation->value_formula = "=H1";
data_validation->validate = LXW_VALIDATION_TYPE_LIST_FORMULA;
data_validation->value_formula = "=$E$4:$G$4";
@endcode
`value_list`:
The `value_list` parameter is used to set a list of strings for a drop down
list. The list should be a `NULL` terminated array of char* strings:
@code
char *list[] = {"open", "high", "close", NULL};
data_validation->validate = LXW_VALIDATION_TYPE_LIST;
data_validation->value_list = list;
@endcode
Note, when using the #LXW_VALIDATION_TYPE_LIST validation with a list of
strings, like in the last example above, Excel stores the strings internally
as a Comma Separated Variable string. The total length for this string,
including commas, cannot exceed the Excel limit of 255 characters. For longer
sets of data you should use a range reference like the previous example above.
`value_datetime`:
The `value_datetime` parameter is used to set the limiting value to which the
#LXW_VALIDATION_TYPE_DATE or #LXW_VALIDATION_TYPE_TIME criteria is applied
using a #lxw_datetime struct:
@code
lxw_datetime datetime1 = {2017, 9, 24, 0, 0, 0};
lxw_datetime datetime2 = { 0, 0, 0, 12, 30, 0};
data_validation->validate = LXW_VALIDATION_TYPE_DATE;
data_validation->criteria = LXW_VALIDATION_CRITERIA_EQUAL;
data_validation->value_datetime = datetime1;
data_validation->validate = LXW_VALIDATION_TYPE_TIME;
data_validation->criteria = LXW_VALIDATION_CRITERIA_EQUAL;
data_validation->value_datetime = datetime2;
@endcode
The `minimum` and `maximum` parameters are used to set the lower and upper
limiting values when the `criteria` is either #LXW_VALIDATION_CRITERIA_BETWEEN
or #LXW_VALIDATION_CRITERIA_NOT_BETWEEN. The parameters are:
- `minimum_number`
- `minimum_formula`
- `minimum_datetime`
- `maximum_number`
- `maximum_formula`
- `maximum_datetime`
They are similar to the `value` parameters described above. For example:
@code
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
data_validation->minimum_number = 1;
data_validation->maximum_number = 10;
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_NOT_BETWEEN;
data_validation->minimum_formula = "=E3";
data_validation->maximum_formula = "=F3";
data_validation->validate = LXW_VALIDATION_TYPE_DATE;
data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
data_validation->minimum_datetime = datetime1;
data_validation->maximum_datetime = datetime2;
@endcode
@section ww_data_validate_options Data validation options
@subsection ww_data_validate_ignore_blank ignore_blank
The `ignore_blank` parameter is used to toggle on and off the 'Ignore blank'
option in the Excel data validation dialog. When the option is on the data
validation is not applied to blank data in the cell. It is on by default:
@code
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
data_validation->minimum_number = 1;
data_validation->maximum_number = 10;
data_validation->ignore_blank = LXW_VALIDATION_OFF;
@endcode
@subsection ww_data_validate_dropdown dropdown
The `dropdown` parameter is used to toggle on and off the 'In-cell dropdown'
option in the Excel data validation dialog. When the option is on a dropdown
list will be shown for `list` validations. It is on by default.
@code
data_validation->validate = LXW_VALIDATION_TYPE_LIST;
data_validation->value_list = list;
data_validation->dropdown = LXW_VALIDATION_OFF;
@endcode
@subsection ww_data_validate_input_title input_title
The `input_title` parameter is used to set the title of the input message that
is displayed when a cell is entered. It has no default value and is only
displayed if the input message is also displayed. See the `input_message`
parameter below.
The maximum title length is 32 characters.
@subsection ww_data_validate_input_message input_message
The `input_message` parameter is used to set the input message that is
displayed when a cell is entered. It has no default value:
@code
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
data_validation->minimum_number = 1;
data_validation->maximum_number = 100;
data_validation->input_title = "Enter an integer:";
data_validation->input_message = "between 1 and 100";
@endcode
The input message generated from the above example is:
@image html data_validate3.png
The message can be split over several lines using newlines. The maximum message
length is 255 characters.
@subsection ww_data_validate_show_input show_input
The `show_input` parameter is used to toggle on and off the 'Show input
message when cell is selected' option in the Excel data validation dialog.
When the option is off an input message is not displayed even if it has been
set using `input_message`. It is on by default.
@subsection ww_data_validate_error_title error_title
The `error_title` parameter is used to set the title of the error message
that is displayed when the data validation criteria is not met. The default
error title is 'Microsoft Excel'. The maximum title length is 32 characters.
@subsection ww_data_validate_error_message error_message
The `error_message` parameter is used to set the error message that is
displayed when a cell is entered. The default error message is "The value you
entered is not valid. A user has restricted values that can be entered into
the cell". A non-default error message can be displayed as follows:
@code
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
data_validation->minimum_number = 1;
data_validation->maximum_number = 100;
data_validation->input_title = "Enter an integer:";
data_validation->input_message = "between 1 and 100";
data_validation->error_title = "Input value is not valid!";
data_validation->error_message = "It should be an integer between 1 and 100";
@endcode
Which give the following message:
@image html data_validate2.png
The message can be split over several lines using newlines. The maximum message
length is 255 characters.
@subsection ww_data_validate_error_type error_type
The `error_type` parameter is used to specify the type of error dialog that is
displayed. There are 3 #lxw_validation_error_types options:
- #LXW_VALIDATION_ERROR_TYPE_STOP, the default.
- #LXW_VALIDATION_ERROR_TYPE_WARNING
- #LXW_VALIDATION_ERROR_TYPE_INFORMATION
@subsection ww_data_validate_show_error show_error
The `show_error` parameter is used to toggle on and off the 'Show error alert
after invalid data is entered' option in the Excel data validation dialog.
When the option is off an error message is not displayed even if it has been
set using `error_message`. It is on by default.
@section ww_data_validate_examples Examples
@code
// Restrict input to an integer between 1 and 10.
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
data_validation->minimum_number = 1;
data_validation->maximum_number = 10;
// Restrict input to an integer not between 1 and 10 (using cell references).
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_NOT_BETWEEN;
data_validation->minimum_formula = "=E3";
data_validation->maximum_formula = "=F3";
// Restrict input to a decimal between 0.1 and 0.5.
data_validation->validate = LXW_VALIDATION_TYPE_DECIMAL;
data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
data_validation->minimum_number = 0.1;
data_validation->maximum_number = 0.5;
// Select a value from a drop down list.
char *list[] = {"open", "high", "close", NULL};
data_validation->validate = LXW_VALIDATION_TYPE_LIST;
data_validation->value_list = list;
// Select a value from a drop down list (using a cell range).
data_validation->validate = LXW_VALIDATION_TYPE_LIST;
data_validation->value_formula = "=$E$4:$G$4";
// Restrict input to a date between 1/1/2008 and 12/12/2008.
lxw_datetime datetime1 = {2008, 1, 1, 0, 0, 0};
lxw_datetime datetime2 = {2008, 12, 12, 0, 0, 0};
data_validation->validate = LXW_VALIDATION_TYPE_DATE;
data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
data_validation->minimum_datetime = datetime1;
data_validation->maximum_datetime = datetime2;
// Restrict input to a string longer than 3 characters.
data_validation->validate = LXW_VALIDATION_TYPE_LENGTH;
data_validation->criteria = LXW_VALIDATION_CRITERIA_GREATER_THAN;
data_validation->value_number = 3;
// Restrict input to a value if a formula is true.
data_validation->validate = LXW_VALIDATION_TYPE_CUSTOM_FORMULA;
data_validation->value_formula = "=AND(F5=50,G5=60)";
// Display a custom info message when integer isn't between 1 and 100.
data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
data_validation->minimum_number = 1;
data_validation->maximum_number = 100;
data_validation->input_title = "Enter an integer:";
data_validation->input_message = "between 1 and 100";
data_validation->error_title = "Input value is not valid!";
data_validation->error_message = "It should be an integer between 1 and 100";
@endcode
For a full example see @ref data_validate.c.
Next: @ref working_with_conditional_formatting
*/
@@ -0,0 +1,111 @@
/**
@page working_with_dates Working with Dates and Times
@tableofcontents
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
Some options for creating or converting dates to the correct format are shown
below.
@section ww_date_struct Writing datetimes with the lxw_datetime struct
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 initialize 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
@section ww_date_unix Writing Unix datetimes
Another alternative when handling dates is [Unix
Time](https://en.wikipedia.org/wiki/Unix_time) which is a common integer time
format. It is defined as the number of seconds since the Unix epoch
(1970-01-01 00:00 UTC).
The `worksheet_write_unixtime()` function can be used to write dates and times
in this format. Negative values can also be used for dates prior to 1970:
@dontinclude dates_and_times03.c
@skip include
@until }
The output from this program is:
@image html date_example03.png
@section ww_date_formats Date formatting
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_times04.c
@skip include
@until return
@until }
@image html date_example04.png
To get date formats that show up in Excel as a "Date" or "Time" number
category see @ref ww_formats_categories.
Next: @ref working_with_charts
*/
@@ -0,0 +1,274 @@
/**
@page working_with_formats Working with Formats
@tableofcontents
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.
@section ww_formats_creating 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
worksheet_set_row (worksheet, 2, format, NULL);
worksheet_set_column(worksheet, 0, 20, format, NULL);
@endcode
@section ww_formats_properties 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() |
@section ww_formats_colors 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.
@section ww_formats_default 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
@section ww_formats_reusing 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.
@section ww_formats_categories Number Format Categories
The `format_set_num_format()` function shown below, is used to set the number
format for numbers used with `worksheet_write_number()`:
@code
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("currency_format.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_format *currency_format = workbook_add_format(workbook);
format_set_num_format(currency_format, "$#,##0.00");
worksheet_write_number(worksheet, 0, 0, 1234.56, currency_format);
workbook_close(workbook);
return 0;
}
@endcode
If the number format you use is the same as one of Excel's built in number
formats then it will have a number category such as "General", "Number",
"Currency", "Accounting", "Date", "Time", "Percentage", "Fraction",
"Scientific", "Text", "Special or "Custom". In the case of the example above
the formatted output shows up as a Number category:
@image html currency_format1.png
If we wanted it to have a different category, such as Currency, then
we would have to match the number format string with the number format used by
Excel. The easiest way to do this is to open the Number Formatting dialog in
Excel and set the format that you want:
@image html currency_format2.png
Then, while still in the dialog, change to Custom. The format displayed is the
format used by Excel.
@image html currency_format3.png
If we put the format that we found (`"[$$-409]#,##0.00"`) into our previous
example and rerun it we will get a number format in the Currency category:
@code
include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("currency_format.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_format *currency_format = workbook_add_format(workbook);
format_set_num_format(currency_format, "[$$-409]#,##0.00");
worksheet_write_number(worksheet, 0, 0, 1234.56, currency_format);
workbook_close(workbook);
return 0;
}
@endcode
Here is the output:
@image html currency_format4.png
The same process can be used to find format strings for "Date" or
"Accountancy" formats.
@section ww_formats_locale Number Formats in different locales
As shown in the previous section the `format_set_num_format()` method is used
to set the number format for libxlsxwriter formats. A common use case is to
set a number format with a "grouping/thousands" separator and a "decimal"
point:
@code
include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("number_format.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_format *number_format = workbook_add_format(workbook);
format_set_num_format(number_format, "#,##0.00");
worksheet_write_number(worksheet, 0, 0, 1234.56, number_format);
workbook_close(workbook);
return 0;
}
@endcode
In the US locale (and some others) where the number "grouping/thousands"
separator is "," and the "decimal" point is "." this would be shown in Excel
as:
@image html currency_format5.png
In other locales these values may be reversed or different. They are generally
set in the "Region" settings of Windows or Mac OS. Excel handles this by
storing the number format in the file format in the US locale, in this case
`#,##0.00`, but renders it according to the regional settings of the host
OS. For example, here is the same, unmodified, output file shown above in a
German locale:
@image html currency_format6.png
And here is the same file in a Russian locale. Note the use of a space as the
"grouping/thousands" separator:
@image html currency_format7.png
In order to replicate Excel's behavior all XlsxWriter programs should use US
locale formatting which will then be rendered in the settings of your host OS.
Next: @ref working_with_colors
*/
@@ -0,0 +1,528 @@
/**
@page working_with_formulas Working with Formulas
@tableofcontents
In general a formula in Excel can be used directly in the
worksheet_write_formula() function:
@code
worksheet_write_formula(worksheet, 0, 0, "=10*B1 + C1", NULL);
@endcode
@image html working_with_formulas1.png
However, there are a few potential issues and differences that the user should
be aware of. These are explained in the following sections.
@section ww_formulas_results Formula Results
Libxlsxwriter doesn't calculate the result 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 will only display the 0
results. Examples of such applications are Excel Viewer, PDF Converters, and
some mobile device applications.
If required, it is also possible to specify the calculated result of the
formula using the `result` parameter for
`worksheet_worksheet_write_formula_num()`:
@code
worksheet_write_formula_num(worksheet, 0, 0, "=2+2", NULL, 4);
@endcode
@section ww_formulas_non_us Non US Excel functions and syntax
Excel stores formulas in the format of the US English version, regardless
of the language or locale of the end-user's version of Excel. Therefore all
formula function names written using libxlsxwriter must be in English:
@code
// The following formula syntax is okay.
worksheet_write_formula(worksheet, 0, 0, "=SUM(1, 2, 3)", NULL);
// The following formula syntax is in French. Will cause error on load.
worksheet_write_formula(worksheet, 0, 1, "=SOMME(1, 2, 3)", NULL);
@endcode
Also, 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
// The following formula syntax is okay.
worksheet_write_formula(worksheet, 0, 0, "=SUM(1, 2, 3)", NULL);
// The following formula use semi-colons. Will cause error on load.
worksheet_write_formula(worksheet, 0, 1, "=SUM(1; 2; 3)", NULL);
@endcode
If you have a non-English version of Excel you can use the following
multi-lingual [Formula Translator](http://en.excel-translator.de/language/)
to help you convert the formula. It can also replace semi-colons with commas.
@section ww_formulas_dynamic_arrays Dynamic Array support
Excel introduced the concept of "Dynamic Arrays" and new functions that use
them in Office 365. The new functions are:
- `FILTER`
- `RANDARRAY`
- `SEQUENCE`
- `SORTBY`
- `SORT`
- `UNIQUE`
- `XLOOKUP`
- `XMATCH`
The following special case functions were also added with Dynamic Arrays:
- `SINGLE`: Explained below in @ref ww_formulas_intersection.
- `ANCHORARRAY`: Explained below in @ref ww_formulas_spill.
- `LAMBDA` and `LET`: Explained below in @ref ww_formulas_lambda.
These functions are all "future functions" and need to written in
libxlsxwriter as follows:
- `_xlfn.ANCHORARRAY`
- `_xlfn.LAMBDA`
- `_xlfn.RANDARRAY`
- `_xlfn.SEQUENCE`
- `_xlfn.SINGLE`
- `_xlfn.SORTBY`
- `_xlfn.UNIQUE`
- `_xlfn.XLOOKUP`
- `_xlfn.XMATCH`
- `_xlfn._xlws.FILTER`
- `_xlfn._xlws.SORT`
Future functions are explained in the section below on @ref
ww_formulas_future.
@subsection ww_formulas_intro Dynamic Arrays - An introduction
Dynamic arrays in Excel are ranges of return values that can change in size
based on the results. For example, a function such as `FILTER()` returns an
array of values that can vary in size depending on the the filter results:
@code
worksheet_write_dynamic_array_formula(worksheet, RANGE("F2:F2"),
"=_xlfn._xlws.FILTER(A1:D17,C1:C17=K2)",
NULL);
@endcode
This formula gives the results shown in the image below. The dynamic range
here is "F2:I5" but it can vary based on the filter criteria.
@image html dynamic_arrays02.png
It is also possible to get dynamic array behavior with older Excel
functions. For example, the Excel function `"=LEN(A1)"` applies to a single
cell and returns a single value but it can also apply to a range of cells and
return a range of values using an array formula like `"{=LEN(A1:A3)}"`. This
type of "static" array behavior is referred to as a CSE (Ctrl+Shift+Enter)
formula and has existed in Excel since early versions. In Office 365 Excel
updated and extended this behavior to create the concept of dynamic arrays. In
Excel 365 you can now write the previous LEN function as `"=LEN(A1:A3)"` and
get a dynamic range of return values. In libxlsxwriter you can use the
`worksheet_write_array_formula()` function to get a static/CSE range and
`worksheet_write_dynamic_array_formula()` to get a dynamic range. For example:
@code
worksheet_write_dynamic_array_formula(worksheet, RANGE("B1:B3"),
"=LEN(A1:A3)",
NULL);
@endcode
Which gives the following result:
@image html intersection03.png
The difference between the two types of array functions is explained in the
Microsoft documentation on [Dynamic array formulas vs. legacy CSE array
formulas](https://support.microsoft.com/en-us/office/dynamic-array-formulas-vs-legacy-cse-array-formulas-ca421f1b-fbb2-4c99-9924-df571bd4f1b4). Note
the use of the word "legacy" here. This, and the documentation itself, is a
clear indication of the future importance of dynamic arrays in Excel.
For a wider and more general introduction to dynamic arrays see the following:
[Dynamic array formulas in Excel](https://exceljet.net/dynamic-array-formulas-in-excel).
The `worksheet_write_dynamic_array_formula()` function takes a `(first_row,
first_col, last_row, last_col)` cell range to define the area that the formula
applies to. However, since the range is dynamic this generally won't be known
in advance in which case you can specify the range with the same start and end
cell. The following range is "F2:F2":
@code
worksheet_write_dynamic_array_formula(worksheet, 1, 5, 1, 5,
"=_xlfn._xlws.FILTER(A1:D17,C1:C17=K2)",
NULL);
@endcode
As a syntactic shortcut you can use the `worksheet_write_dynamic_formula()`
function which only requires the start cell:
@code
worksheet_write_dynamic_formula(worksheet, 1, 5,
"=_xlfn._xlws.FILTER(A1:D17,C1:C17=K2)",
NULL);
@endcode
@subsection ww_formulas_intersection Dynamic Arrays - The Implicit Intersection Operator "@"
The Implicit Intersection Operator, "@", is used by Excel 365 to indicate a
position in a formula that is implicitly returning a single value when a range
or an array could be returned.
We can see how this operator works in practice by considering the formula we
used in the last section: `=LEN(A1:A3)`. In Excel versions without support for
dynamic arrays, i.e. prior to Excel 365, this formula would operate on a
single value from the input range and return a single value, like the
following in Excel 2011:
@image html intersection01.png
There is an implicit conversion here of the range of input values, "A1:A3", to
a single value "A1". Since this was the default behavior of older versions of
Excel this conversion isn't highlighted in any way. But if you open the same
file in Excel 365 it will appear as follows:
@image html intersection02.png
The result of the formula is the same (this is important to note) and it still
operates on, and returns, a single value. However the formula now contains a
"@" operator to show that it is implicitly using a single value from the given
range.
Finally, if you entered this formula in Excel 365, or with
`worksheet_write_dynamic_array_formula()` in libxlsxwriter, it would operate
on the entire range and return an array of values:
@image html intersection03.png
If you are encountering the Implicit Intersection Operator "@" for the first
time then it is probably from a point of view of "why is Excel/libxlsxwriter
putting @s in my formulas". In practical terms if you encounter this operator,
and you don't intend it to be there, then you should probably write the
formula as a CSE or dynamic array function using
`worksheet_write_array_formula()` or `worksheet_write_dynamic_array_formula()`.
A full explanation of this operator is shown in the Microsoft documentation on
the [Implicit intersection operator: \@]
(https://support.microsoft.com/en-us/office/implicit-intersection-operator-ce3be07b-0101-4450-a24e-c1c999be2b34?ui=en-us&rs=en-us&ad=us>).
One important thing to note is that the "@" operator isn't stored with the
formula. It is just displayed by Excel 365 when reading "legacy"
formulas. However, it is possible to write it to a formula, if necessary,
using `_xlfn.SINGLE()`. The unusual cases where this may be necessary are
shown in the linked document in the previous paragraph.
@subsection ww_formulas_spill Dynamic Arrays - The Spilled Range Operator "#"
In the section above on @ref ww_formulas_intro we saw that dynamic array formulas
can return variable sized ranges of results. The Excel documentation refers to
this as a "Spilled" range/array from the idea that the results spill into the
required number of cells. This is explained in the Microsoft documentation on
[Dynamic array formulas and spilled array behavior]
(https://support.microsoft.com/en-us/office/dynamic-array-formulas-and-spilled-array-behavior-205c6b06-03ba-4151-89a1-87a7eb36e531).
Since a spilled range is variable in size a new operator is required to refer
to the range. This operator is the [Spilled range operator]
(https://support.microsoft.com/en-us/office/spilled-range-operator-3dd5899f-bca2-4b9d-a172-3eae9ac22efd)
and it is represented by "#". For example, the range `F2#` in the image
below is used to refer to a dynamic array returned by `UNIQUE()` in the cell
`F2`:
@image html spill01.png
Unfortunately, Excel doesn't store the formula like this and in libxlsxwriter
you need to use the explicit function `_xlfn.ANCHORARRAY()` to refer to a
spilled range. The example in the image above was generated using the
following:
@code
// Same as '=COUNTA(F2#)' in Excel.
worksheet_write_dynamic_formula(worksheet9, CELL("J2"),
"=COUNTA(_xlfn.ANCHORARRAY(F2))",
NULL);
@endcode
@subsection ww_formulas_lambda The Excel 365 LAMBDA() function
Recent versions of Excel 365 have introduced a powerful new
function/feature called `LAMBDA()`. This is similar to
[lambda expressions]
(https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=msvc-160)
in C++ (and other languages).
Consider the following Excel example which converts the variable `temp` from Fahrenheit to Celsius:
LAMBDA(temp, (5/9) * (temp-32))
This could be called in Excel with an argument:
=LAMBDA(temp, (5/9) * (temp-32))(212)
Or assigned to a defined name and called as a user defined function:
=ToCelsius(212)
An libxlsxwriter example that replicates the described Excel functionality is
shown below:
@code
// Write the lambda as a function.
worksheet_write_dynamic_formula(worksheet, CELL("A2"),
"=_xlfn.LAMBDA(_xlpm.temp, (5/9) * (_xlpm.temp-32))(32)",
NULL);
// Create the lambda function as a defined name and write it as a dynamic formula.
workbook_define_name(workbook,
"ToCelsius",
"=_xlfn.LAMBDA(_xlpm.temp, (5/9) * (_xlpm.temp-32))");
worksheet_write_dynamic_formula(worksheet, CELL("A3"), "=ToCelsius(212)", NULL);
@endcode
Note, that the formula name must have a "_xlfn." prefix and the parameters in
the `LAMBDA()` function must have a "_xlpm." prefix for compatibility with
how the formulas are stored in Excel. These prefixes won't show up in the
formula, as shown in the image.
@image html lambda01.png
The `LET()` function is often used in conjunction with `LAMBDA()` to assign
names to calculation results.
@section ww_formulas_future Formulas added in Excel 2010 and later
Excel 2010 and later versions added functions which weren't defined in the
original file specification. These functions are referred to by Microsoft as
"Future Functions". Examples of these functions are `ACOT`, `CHISQ.DIST.RT` ,
`CONFIDENCE.NORM`, `STDEV.P`, `STDEV.S` and `WORKDAY.INTL`.
When written using `worksheet_write_formula()` these functions need to be
fully qualified with a `_xlfn.` (or other) prefix as they are shown the list
below. For example:
@code
worksheet_write_formula(worksheet, 0, 0, "=_xlfn.STDEV.S(B1:B10)", NULL);
@endcode
They will appear without the prefix in Excel:
@image html working_with_formulas2.png
The following list is taken from
[MS XLSX extensions documentation on future functions](http://msdn.microsoft.com/en-us/library/dd907480%28v=office.12%29.aspx).
| Future Functions |
| -------------------------------- |
| `_xlfn.ACOT` |
| `_xlfn.ACOTH` |
| `_xlfn.AGGREGATE` |
| `_xlfn.ARABIC` |
| `_xlfn.BASE` |
| `_xlfn.BETA.DIST` |
| `_xlfn.BETA.INV` |
| `_xlfn.BINOM.DIST` |
| `_xlfn.BINOM.DIST.RANGE` |
| `_xlfn.BINOM.INV` |
| `_xlfn.BITAND` |
| `_xlfn.BITLSHIFT` |
| `_xlfn.BITOR` |
| `_xlfn.BITRSHIFT` |
| `_xlfn.BITXOR` |
| `_xlfn.CEILING.MATH` |
| `_xlfn.CEILING.PRECISE` |
| `_xlfn.CHISQ.DIST` |
| `_xlfn.CHISQ.DIST.RT` |
| `_xlfn.CHISQ.INV` |
| `_xlfn.CHISQ.INV.RT` |
| `_xlfn.CHISQ.TEST` |
| `_xlfn.COMBINA` |
| `_xlfn.CONCAT` |
| `_xlfn.CONFIDENCE.NORM` |
| `_xlfn.CONFIDENCE.T` |
| `_xlfn.COT` |
| `_xlfn.COTH` |
| `_xlfn.COVARIANCE.P` |
| `_xlfn.COVARIANCE.S` |
| `_xlfn.CSC` |
| `_xlfn.CSCH` |
| `_xlfn.DAYS` |
| `_xlfn.DECIMAL` |
| `ECMA.CEILING` |
| `_xlfn.ERF.PRECISE` |
| `_xlfn.ERFC.PRECISE` |
| `_xlfn.EXPON.DIST` |
| `_xlfn.F.DIST` |
| `_xlfn.F.DIST.RT` |
| `_xlfn.F.INV` |
| `_xlfn.F.INV.RT` |
| `_xlfn.F.TEST` |
| `_xlfn.FILTERXML` |
| `_xlfn.FLOOR.MATH` |
| `_xlfn.FLOOR.PRECISE` |
| `_xlfn.FORECAST.ETS` |
| `_xlfn.FORECAST.ETS.CONFINT` |
| `_xlfn.FORECAST.ETS.SEASONALITY` |
| `_xlfn.FORECAST.ETS.STAT` |
| `_xlfn.FORECAST.LINEAR` |
| `_xlfn.FORMULATEXT` |
| `_xlfn.GAMMA` |
| `_xlfn.GAMMA.DIST` |
| `_xlfn.GAMMA.INV` |
| `_xlfn.GAMMALN.PRECISE` |
| `_xlfn.GAUSS` |
| `_xlfn.HYPGEOM.DIST` |
| `_xlfn.IFNA` |
| `_xlfn.IFS` |
| `_xlfn.IMCOSH` |
| `_xlfn.IMCOT` |
| `_xlfn.IMCSC` |
| `_xlfn.IMCSCH` |
| `_xlfn.IMSEC` |
| `_xlfn.IMSECH` |
| `_xlfn.IMSINH` |
| `_xlfn.IMTAN` |
| `_xlfn.ISFORMULA` |
| `ISO.CEILING` |
| `_xlfn.ISOWEEKNUM` |
| `_xlfn.LOGNORM.DIST` |
| `_xlfn.LOGNORM.INV` |
| `_xlfn.MAXIFS` |
| `_xlfn.MINIFS` |
| `_xlfn.MODE.MULT` |
| `_xlfn.MODE.SNGL` |
| `_xlfn.MUNIT` |
| `_xlfn.NEGBINOM.DIST` |
| `NETWORKDAYS.INTL` |
| `_xlfn.NORM.DIST` |
| `_xlfn.NORM.INV` |
| `_xlfn.NORM.S.DIST` |
| `_xlfn.NORM.S.INV` |
| `_xlfn.NUMBERVALUE` |
| `_xlfn.PDURATION` |
| `_xlfn.PERCENTILE.EXC` |
| `_xlfn.PERCENTILE.INC` |
| `_xlfn.PERCENTRANK.EXC` |
| `_xlfn.PERCENTRANK.INC` |
| `_xlfn.PERMUTATIONA` |
| `_xlfn.PHI` |
| `_xlfn.POISSON.DIST` |
| `_xlfn.QUARTILE.EXC` |
| `_xlfn.QUARTILE.INC` |
| `_xlfn.QUERYSTRING` |
| `_xlfn.RANK.AVG` |
| `_xlfn.RANK.EQ` |
| `_xlfn.RRI` |
| `_xlfn.SEC` |
| `_xlfn.SECH` |
| `_xlfn.SHEET` |
| `_xlfn.SHEETS` |
| `_xlfn.SKEW.P` |
| `_xlfn.STDEV.P` |
| `_xlfn.STDEV.S` |
| `_xlfn.SWITCH` |
| `_xlfn.T.DIST` |
| `_xlfn.T.DIST.2T` |
| `_xlfn.T.DIST.RT` |
| `_xlfn.T.INV` |
| `_xlfn.T.INV.2T` |
| `_xlfn.T.TEST` |
| `_xlfn.TEXTJOIN` |
| `_xlfn.UNICHAR` |
| `_xlfn.UNICODE` |
| `_xlfn.VAR.P` |
| `_xlfn.VAR.S` |
| `_xlfn.WEBSERVICE` |
| `_xlfn.WEIBULL.DIST` |
| `WORKDAY.INTL` |
| `_xlfn.XOR` |
| `_xlfn.Z.TEST` |
The dynamic array functions shown in the @ref ww_formulas_dynamic_arrays
section above are also future functions:
| Dynamic Array Functions |
| -------------------------------- |
| `_xlfn.ANCHORARRAY` |
| `_xlfn.LAMBDA` |
| `_xlfn.RANDARRAY` |
| `_xlfn.SEQUENCE` |
| `_xlfn.SINGLE` |
| `_xlfn.SORTBY` |
| `_xlfn.UNIQUE` |
| `_xlfn.XLOOKUP` |
| `_xlfn.XMATCH` |
| `_xlfn._xlws.FILTER` |
| `_xlfn._xlws.SORT` |
@section ww_formulas_errors Dealing with formula errors
If there is an error in the syntax of a formula it is usually displayed in
Excel as @c \#NAME?. Alternatively you may get a warning from Excel when the
file is loaded. If you encounter an error like this you can debug it as
follows:
1. Ensure the formula is valid in Excel by copying and pasting it into a
cell. Note, this should be done in Excel and @b not other applications
such as OpenOffice or LibreOffice since they may have slightly different
syntax.
2. Ensure the formula is using comma separators instead of semi-colons, see
@ref ww_formulas_non_us above.
3. Ensure the formula is in English, see @ref ww_formulas_non_us above.
4. Ensure that the formula doesn't contain an Excel 2010+ future function as
listed above (@ref ww_formulas_future). If it does then ensure that the
correct prefix is used.
5. If the function loads in Excel but appears with one or more ``@`` symbols
added then it is probably an array function and should be written using
`worksheet_write_array_formula()` or
`worksheet_write_dynamic_array_formula()` (see the sections above on @ref
ww_formulas_dynamic_arrays and @ref ww_formulas_intersection).
Finally if you have completed all the previous steps and still get a
@c \#NAME? error you can examine a valid Excel file to see what the correct
syntax should be. To do this you should create a valid formula in Excel and
save the file. You can then examine the XML in the unzipped file.
The following shows how to do that using Linux `unzip` and `libxml's
[xmllint](http://xmlsoft.org/xmllint.html) to format the XML for clarity:
$ unzip myfile.xlsx -d myfile
$ xmllint --format myfile/xl/worksheets/sheet1.xml | grep '</f>'
<f>SUM(1, 2, 3)</f>
Next: @ref working_with_dates
*/
@@ -0,0 +1,180 @@
/**
@page working_with_macros Working with VBA Macros
@tableofcontents
This section explains how to add a VBA file containing functions or macros to
an libxlsxwriter workbook.
@dontinclude macro.c
@skipline include
@until return
@skipline }
@image html macros.png
@section ww_macros_xlsm_format The Excel XLSM file format
An Excel `xlsm` file is exactly the same as an `xlsx` file except that is
contains an additional `vbaProject.bin` file which contains functions and/or
macros. Excel uses a different extension to differentiate between the two file
formats since files containing macros are usually subject to additional
security checks.
@section ww_macros_include How VBA macros are included in libxlsxwriter files
The `vbaProject.bin` file is a binary OLE COM container. This was the format
used in older `xls` versions of Excel prior to Excel 2007. Unlike all of the
other components of an xlsx/xlsm file the data isn't stored in XML
format. Instead the functions and macros as stored as a pre-parsed binary
format. As such it wouldn't be feasible to define macros and create a
`vbaProject.bin` file from scratch (at least not in the remaining lifespan and
interest levels of the author).
Instead a workaround is used to extract `vbaProject.bin` files from existing
xlsm files and then add these to libxlsxwriter generated files.
@section ww_macros_extract The vba_extract.py utility
The `vba_extract.py` Python utility is used to extract the `vbaProject.bin`
binary from an Excel 2007+ xlsm file. The utility is included in the
libxlsxwriter examples directory:
$ python examples/vba_extract.py macro_file.xlsm
Extracted: vbaProject.bin
You can also install `vba_extract.py` into your system path by installing the
Python xlsxwriter module:
$ pip install xlsxwriter
...
$ vba_extract.py
Utility to extract a vbaProject.bin binary from an
Excel 2007+ xlsm macro file ...
@section ww_macros_adding Adding the VBA macros to a libxlsxwriter file
Once the `vbaProject.bin` file has been extracted it can be added to the
libxlsxwriter workbook using the `workbook_add_vba_project()` function:
@code
workbook_add_vba_project(workbook, "./vbaProject.bin");
@endcode
@note The name doesn't have to be `vbaProject.bin`. Any suitable path/name for
an existing VBA bin file will do.
If the VBA file contains functions you can then refer to them in calculations
using `worksheet_write_formula()`:
@code
worksheet_write_formula(0, 0, "=MyMortgageCalc(200000, 25)")
@endcode
Excel files that contain functions and macros should use an `xlsm` extension
or else Excel will complain and possibly not open the file:
@code
lxw_workbook *workbook = new_workbook("macro.xlsm");
@endcode
It is also possible to assign a macro to a button that is inserted into a
worksheet using the `worksheet_insert_button()` function:
@code
lxw_button_options options = {.caption = "Press Me",
.macro = "say_hello"};
worksheet_insert_button(worksheet, 2, 1, &options);
@endcode
See the full example at @ref macro.c.
It may be necessary to specify a more explicit macro name prefixed by the
workbook VBA name as follows:
@code
lxw_button_options options = {.caption = "Press Me",
.macro = "ThisWorkbook.say_hello"};
worksheet_insert_button(worksheet, 2, 1, &options);
@endcode
@note Button is the only VBA Control supported by libxlsxwriter and due to the
implementation effort required it is unlikely that any other form elements
will be added in the future.
@section ww_macros_codenames Setting the VBA codenames
VBA macros generally refer to workbook and worksheet objects. If the VBA
codenames aren't specified explicitly then libxlsxwriter will use the Excel
defaults of `ThisWorkbook` and `Sheet1`, `Sheet2` etc.
If the macro uses other codenames you can set them using the
`workbook_set_vba_name()` and `worksheet_set_vba_name()` functions as follows:
@code
// Set the VBA codenames for the workbook and any worksheets.
workbook_set_vba_name (workbook, "MyWorkbook");
worksheet_set_vba_name(worksheet, "MySheet1");
worksheet_set_vba_name(worksheet, "MySheet2");
@endcode
@note This step is particularly important for macros created with non-English
versions of Excel.
You can find the names that are used in the VBA editor or by unzipping the
`xlsm` file and grepping the files. The following shows how to do that using
[libxml's xmllint](http://xmlsoft.org/xmllint.html) to format the XML for
clarity:
$ unzip myfile.xlsm -d myfile
$ xmllint --format `find myfile -name "*.xml" | xargs` | grep "Pr.*codeName"
<workbookPr codeName="MyWorkbook" defaultThemeVersion="124226"/>
<sheetPr codeName="MySheet1"/>
@note This step is particularly important for macros created with non-English
versions of Excel.
@section ww_macros_debugging What to do if it doesn't work
The libxlsxwriter test suite contains several tests to ensure that this feature
works and there is a working example as shown above. However, there is no
guarantee that it will work in all cases. Some effort may be required and some
knowledge of VBA will certainly help. If things don't work out here are some
things to try:
1. Start with a simple macro file, ensure that it works and then add complexity.
2. Check the code names that macros use to refer to the workbook and
worksheets (see the previous section above). In general VBA uses a code
name of `ThisWorkbook` to refer to the current workbook and the sheet name
(such as `Sheet1`) to refer to the worksheets. These are the defaults used
by libxlsxwriter. If the macro uses other names, or the macro was extracted
from an non-English language version of Excel, then you can specify the
appropriate names using the `workbook_set_vba_name()` and
`worksheet_set_vba_name()` functions:
@code
// Set the VBA codenames for the workbook and any worksheets.
workbook_set_vba_name (workbook, "MyWorkbook");
worksheet_set_vba_name(worksheet, "MySheet1");
worksheet_set_vba_name(worksheet, "MySheet2");
@endcode
3. Try to extract the macros from an Excel 2007 file. The method should work
with macros from later versions (it was also tested with Excel 2010
macros). However there may be features in the macro files of more recent
version of Excel that aren't backward compatible.
Next: @ref examples
*/
@@ -0,0 +1,97 @@
/**
@page working_with_memory Working with Memory and Performance
@tableofcontents
@section ww_mem_constant Constant Memory Mode
By default libxlsxwriter holds all cell data in memory to allow non-sequential
data storage. The effect of this is that for large files libxlsxwriter can
consume a lot of memory.
Fortunately, this memory usage can be reduced almost completely by using
workbook_new_opt() and the lxw_workbook_options `constant_memory` property:
@dontinclude constant_memory.c
@skipline include
@until return
@skipline }
This optimization works by flushing each row after a subsequent row is written.
In this way the largest amount of data held in memory for a worksheet is the
amount of data required to hold a single row of data.
If required, this memory usage can be reduced even more by setting
`LXW_COL_MAX` in worksheet.c from 16384 down to a value that matches the
maximum column that is likely to be encountered.
The trade-off when using `constant_memory` mode is that data must be added
sequentially in row order and you won't be able to take advantage of any
functions that manipulate cell data after it is written. For example:
- In `constant_memory` mode `worksheet_set_row()` can only be used when
writing data to the current row. This has an additional knock on effect that
images won't scale properly over row heights adjusted with
`%worksheet_set_row()`.
- A merged range set with `worksheet_merge_range()` can only be applied to the
current row (which in general isn't very useful).
@subsection ww_mem_row_order Row Column Order
Since each new row flushes the previous row, data must be written in sequential
row order when `constant_memory` mode is on:
@code
lxw_workbook *workbook = workbook_new_opt("constant_memory.xlsx", &options);
...
// !! Don't use "column x row" order in 'constant_memory' mode. Only
// the first column of data will be written.
for (col = 0; col < max_col; col++) {
for (row = 0; row < max_row; row++) {
worksheet_write_number(worksheet, row, col, 123.45, NULL);
}
}
@endcode
@subsection ww_mem_temp Constant memory mode and the /tmp directory
The libxlsxwriter library uses temporary files stored in the system `/tmp`
directory prior to creating the final xlsx file. In `constant_memory` mode the
library uses additional temporary file storage for worksheet data. This can
lead to an issue on OSes that map the `/tmp` directory into memory since it is
possible for a libxlsxwriter application to consume the "system" memory via
disk usage even though the "process" memory remains constant.
This is generally only an issue with embedded Linux systems with limited
amounts of system memory. In these cases you should use an alternative
temporary file location by using the `tmpdir` option of #lxw_workbook_options
and workbook_new_opt().
@subsection ww_mem_inline_strings Inline strings
Another optimization that is used to reduce memory usage in `constant_memory`
mode is that cell strings aren't stored in an Excel structure call "shared
strings" and instead are written "in-line".
This is a documented Excel feature that is supported by most spreadsheet
applications. However, it isn't supported by some some spreadsheet viewer
applications. Also, the size of the output file can increase by 20%-100%
depending on the amount of repeated string data.
@section ww_mem_performance Performance
Currently the library is optimized but not highly optimized. Also, the library
is currently single threaded.
Compiling with the embedded but option dtoa library is 40-50% faster for raw
numeric data. See @ref gsg_dtoa.
Next: @ref working_with_macros
*/
@@ -0,0 +1,176 @@
/**
@page working_with_object_positioning Working with Object Positioning
Libxlsxwriter positions worksheet objects such as images and charts in
worksheets by calculating precise co-ordinates based on the object size, it's
DPI (for images) and any scaling that the user specifies. It also takes into
account the heights and widths of the rows and columns that the object
crosses. In this way objects maintain their original sizes even if the rows or
columns underneath change size or are hidden.
For example:
@code
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("images.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
// Original image.
worksheet_insert_image(worksheet, CELL("B2"), "logo.png");
// Same as original, despite row/col changes.
worksheet_insert_image(worksheet, CELL("E8"), "logo.png");
// Make column F narrower.
worksheet_set_column(worksheet, COLS("F:F"), 2, NULL);
// Hide row 12 (zero indexed).
lxw_row_col_options row_options = {.hidden = LXW_TRUE};
worksheet_set_row_opt(worksheet, 11, LXW_DEF_ROW_HEIGHT, NULL, &row_options);
workbook_close(workbook);
return 0;
}
@endcode
@image html object_position1.png
As can be seen the inserted images are the same size even though the second
image crosses changed rows and columns.
However, there are two cases where the image scale may change with row or
columns changes. These are explained in the next two sections.
@section ww_object_position_scaling Object scaling due to automatic row height adjustment
The scaling of a image may be affected if is crosses a row that has its
default height changed due to a font that is larger than the default font size
or that has text wrapping turned on. In these cases Excel will automatically
calculate a row height based on the text when it loads the file. Since this
row height isn't available to Libxlsxwriter when it creates the file the object
may appear as if it is sized incorrectly. For example::
@code
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("images.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_format *wrap = workbook_add_format(workbook);
format_set_text_wrap(wrap);
worksheet_write_string(worksheet, CELL("A10"), "Some text that wraps", wrap);
worksheet_insert_image(worksheet, CELL("B1"), "logo.png");
worksheet_insert_image(worksheet, CELL("B10"), "logo.png");
workbook_close(workbook);
return 0;
}
@endcode
@image html object_position2.png
As can be seen the second inserted image is distorted, compared to the first,
due to the row being scaled automatically. To avoid this you should explicitly
set the height of the row using `worksheet_set_row()` if it crosses an
inserted object.
@section ww_object_position_options Object Positioning with Cell Moving and Sizing
Excel supports three options for "Object Positioning" within a worksheet:
@image html object_position3.png
Image and chart objects in Libxlsxwriter emulate these options using the
`object_position` parameter in #lxw_image_options and #lxw_chart_options:
@code
lxw_image_options options = {.object_position = LXW_OBJECT_MOVE_AND_SIZE};
worksheet_insert_image_opt(worksheet, CELL("E9"), "red.png", &options);
@endcode
Where `object_position` has one of the following allowable values from
#lxw_object_position:
1. #LXW_OBJECT_MOVE_AND_SIZE: Move and size with cells. This is the Excel
default for charts.
2. #LXW_OBJECT_MOVE_DONT_SIZE: Move but dont size with cells. This is the
Excel default for images.
3. #LXW_OBJECT_DONT_MOVE_DONT_SIZE: Dont move or size with cells.
4. #LXW_OBJECT_MOVE_AND_SIZE_AFTER: Same as Option 1 to "move and size with
cells" except Libxlsxwriter applies hidden cells after the object is
inserted.
Option 4 appears in Excel as Option 1. However, the worksheet object is sized
to take hidden rows or columns into account. This allows the user to hide an
image in a cell, possibly as part of an autofilter. For example:
@code
#include "xlsxwriter.h"
int main() {
lxw_workbook *workbook = workbook_new("images.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options image_options = {.object_position = LXW_OBJECT_MOVE_AND_SIZE_AFTER};
worksheet_insert_image( worksheet, CELL("B4"), "logo.png");
worksheet_insert_image_opt(worksheet, CELL("B13"), "logo.png", &image_options);
// Hide the rows that contain the images.
lxw_row_col_options row_options = {.hidden = LXW_TRUE};
for (int row_num = 1; row_num < 22; row_num++)
worksheet_set_row_opt(worksheet, row_num, LXW_DEF_ROW_HEIGHT, NULL, &row_options);
workbook_close(workbook);
return 0;
}
@endcode
@image html object_position4.png
In this example the first inserted image is visible over the hidden rows
whilst the second image is hidden with the rows. Unhiding the rows in Excel
would reveal the second image.
@section ww_object_position_sizing Image sizing and DPI
When an image is imported into Excel the DPI (dots per inch) resolution of the
image is taken into account. Excel sizes the image according to a base DPI of
96 dpi. Therefore an image with a DPI of 72 may appear slightly larger when
imported into Excel while an image with a DPI of 200 may appear twice as
small. Libxlsxwriter also reads the DPI of the images that the user inserts
into a worksheet and stores the image dimensions in the same way that Excel
does. If it cannot determine the DPI of the image it uses a default of 96.
@section ww_object_position_image_issues Reporting issues with image insertion
A lot of work has gone into ensuring that Libxlsxwriter inserts images into
worksheets in exactly the same way that Excel does, even though the required
calculations and units are arcane. There are over 80 test cases that check
image insertion against files created in Excel to ensure that Libxlsxwriter's
handling of images is correct.
As such, before reporting any issues with image handling in Libxlsxwriter
please check how the same image is handled in Excel (not OpenOffice,
LibreOffice or other third party applications). If you do report an issue
please use the Libxlsxwriter [Issue tracker is on GitHub][issue_tracker] that
demonstrates the issue.
[issue_tracker]: https://github.com/jmcnamara/libxlsxwriter/issues
Next: @ref working_with_autofilters
*/
@@ -0,0 +1,130 @@
/**
@page working_with_outlines Working with Outlines and Grouping
Excel allows you to group rows or columns so that they can be hidden or
displayed with a single mouse click. This feature is referred to as Outlines
and Grouping.
Outlines can reduce complex data down to a few salient sub-totals or
summaries. For example the following is a worksheet with three outlines.
@image html outline1.png
Rows 2 to 11 are grouped at level 1 and rows 2 to 5 and 7 to 10 are grouped at
level 2. The lines at the left hand side are called "outline level" bars and
the level is shown by the small numeral above the outline.
Clicking the minus sign on each of the level 2 outlines will collapse and hide
the data as shown below.
@image html outline5.png
The minus sign changes to a plus sign to indicate that the data in the outline
is hidden. This shows the usefulness of outlines: with 2 mouse clicks we have
reduced the amount of visual data down to 2 sub-totals and a master total.
Finally, clicking on the minus sign on the level 1 outline will collapse the
remaining rows as follows:
@image html outline6.png
@section ww_outlines_grouping Outlines and Grouping in libxlsxwriter
Grouping in `libxlsxwriter` is achieved by setting the outline level via the
`worksheet_set_row_opt()` and `worksheet_set_column_opt()` worksheet
functions:
Adjacent row or columns with the same outline level are grouped together into a
single outline.
The `options` parameter is a #lxw_row_col_options struct. It has the following
members:
- `'hidden'`
- `'level'`
- `'collapsed'`
Options can be set as follows, for example to set up an outline for rows:
@code
// The option structs with the outline level set.
lxw_row_col_options options1 = {.hidden = 0, .level = 2, .collapsed = 0};
lxw_row_col_options options2 = {.hidden = 0, .level = 1, .collapsed = 0};
// Set the row options with the outline level.
worksheet_set_row_opt(worksheet, 1, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 2, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 3, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 4, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 5, LXW_DEF_ROW_HEIGHT, NULL, &options2);
worksheet_set_row_opt(worksheet, 6, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 7, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 8, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 9, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 10, LXW_DEF_ROW_HEIGHT, NULL, &options2);
@endcode
@image html outline1.png
Or an outline for columns:
@code
lxw_row_col_options options1 = {.hidden = 0, .level = 1, .collapsed = 0};
worksheet_set_column_opt(worksheet, COLS("B:G"), 5, NULL, &options1);
@endcode
@image html outline8.png
The following example sets an outline level of 1 for rows 1 to 4
(zero-indexed) and columns B to G. The parameters `height`, `width` and
`cell_format` are assigned default values:
@code
lxw_row_col_options options1 = {.hidden = 0, .level = 1, .collapsed = 0};
worksheet_set_row_opt(worksheet, 1, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 2, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 3, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 4, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_column_opt(worksheet, COLS("B:G"), LXW_DEF_COL_WIDTH, NULL, &options);
@endcode
@image html outline3.png
Rows and columns can be collapsed by setting the `hidden` member for the
hidden rows/columns and setting the `collapsed` member for the row/column that
has the collapsed `'+'` symbol:
@code
lxw_row_col_options options1 = {.hidden = 1, .level = 1, .collapsed = 0};
lxw_row_col_options options2 = {.hidden = 0, .level = 0, .collapsed = 1};
worksheet_set_row_opt(worksheet, 1, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 2, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 3, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 4, LXW_DEF_ROW_HEIGHT, NULL, &options1);
worksheet_set_row_opt(worksheet, 5, LXW_DEF_ROW_HEIGHT, NULL, &options2);
worksheet_set_column_opt(worksheet, COLS("B:G"), LXW_DEF_COL_WIDTH, NULL, &options1);
worksheet_set_column_opt(worksheet, COLS("H:H"), LXW_DEF_COL_WIDTH, NULL, &options2);
@endcode
@image html outline7.png
Excel allows up to 7 outline levels. Therefore the `level` parameter should
be in the range `0 <= level <= 7`.
@image html outline4.png
Some additional outline properties can be set via the
`worksheet_outline_settings()` worksheet function.
Next: @ref working_with_memory
*/
@@ -0,0 +1,453 @@
/**
@page working_with_tables Working with Worksheet Tables
@tableofcontents
Tables in Excel are a way of grouping a range of cells into a single entity
that has common formatting or that can be referenced from formulas. Tables can
have column headers, autofilters, total rows, column formulas and default
formatting.
@image html tables12.png
For a general introduction to this Excel feature see [An Overview of Excel
Tables](http://office.microsoft.com/en-us/excel-help/overview-of-excel-tables-HA010048546.aspx)
in the Microsoft Office documentation.
@section ww_tables_add_table Adding a table to a worksheet
Tables are added to a worksheet using the `worksheet_add_table()` function:
@code
worksheet_add_table(worksheet, 2, 1, 6, 5, NULL);
@endcode
Or more explicitly using the RANGE() macro:
@code
worksheet_add_table(worksheet, RANGE("B3:F7"), NULL); //Same as above.
@endcode
@image html tables1.png
The `worksheet_add_table()` `options` parameter should be a pointer to a
lxw_table_options struct with the parameters that describe the table options:
@code
worksheet_add_table(worksheet, 2, 1, 6, 5, &options);
@endcode
These options are explained in the sections below. There are no required
parameters and the `options` parameter is itself optional, in which case you
can specify NULL and get the default table parameters.
You should take care not to overlap worksheet tables as this is not allowed by
Excel and will cause an error when the file is loaded.
@note Tables aren't available in libxlsxwriter when using `constant_memory`
mode in `workbook_new_opt()`.
@subsection ww_tables_header_row Parameter: no_header_row
The `no_header_row` parameter can be used to turn off the header row in the
table. It is on by default:
@code
lxw_table_options options = {.no_header_row = LXW_TRUE};
worksheet_add_table(worksheet, RANGE("B4:F7"), &options);
@endcode
@image html tables4.png
Without this option the header row will contain default captions such as
`Column 1`, ``Column 2``, etc. These captions can be overridden using the
`columns` parameter shown below.
@subsection ww_tables_autofilter Parameter: no_autofilter
The `no_autofilter` parameter can be used to turn off the autofilter in the
header row. It is on by default:
@code
lxw_table_options options = {.no_autofilter = LXW_TRUE};
worksheet_add_table(worksheet, RANGE("B3:F7"), &options);
@endcode
@image html tables3.png
The autofilter is only shown if the `no_header_row` parameter is off (the
default). Filter conditions within the table are not supported.
@subsection ww_tables_banded_rows Parameter: no_banded_rows
The `no_banded_rows` parameter can be used to turn off the rows of alternating
color in the table. It is on by default:
@code
lxw_table_options options = {.no_banded_rows = LXW_TRUE};
worksheet_add_table(worksheet, RANGE("B3:F7"), &options);
@endcode
@image html tables6.png
@subsection ww_tables_banded_columns Parameter: banded_columns
The `banded_columns` parameter can be used to used to create columns of
alternating color in the table. It is off by default:
@code
lxw_table_options options = {.banded_columns = LXW_TRUE};
worksheet_add_table(worksheet, RANGE("B3:F7"), &options);
@endcode
The banded columns formatting is shown in the image in the previous section
above.
@subsection ww_tables_first_column Parameter: first_column
The `first_column` parameter can be used to highlight the first column of the
table. The type of highlighting will depend on the `style_type` of the table.
It may be bold text or a different color. It is off by default:
@code
lxw_table_options options = {.first_column = LXW_TRUE, .last_column = LXW_TRUE};
worksheet_add_table(worksheet, RANGE("B3:F7"), &options);
@endcode
@image html tables5.png
@subsection ww_tables_last_column Parameter: last_column
The `last_column` parameter can be used to highlight the last column of the
table. The type of highlighting will depend on the `style` of the table. It
may be bold text or a different color. It is off by default:
@code
lxw_table_options options = {.first_column = LXW_TRUE, .last_column = LXW_TRUE};
worksheet_add_table(worksheet, RANGE("B3:F7"), &options);
@endcode
The `last_column` formatting is shown in the image in the previous section
above.
@subsection ww_tables_style Parameter: style_type and style_type_number
The `style_type` parameter can be used to set the style of the table, in
conjunction with the `style_type_number` parameter:
@code
lxw_table_options options = {
.style_type = LXW_TABLE_STYLE_TYPE_LIGHT,
.style_type_number = 11,
};
worksheet_add_table(worksheet, RANGE("B3:G8"), &options);
@endcode
@image html tables11.png
There are three types of table style in Excel: Light, Medium and Dark which
are represented using the #lxw_table_style_type enum values:
- #LXW_TABLE_STYLE_TYPE_LIGHT
- #LXW_TABLE_STYLE_TYPE_MEDIUM
- #LXW_TABLE_STYLE_TYPE_DARK
Within those ranges there are between 11 and 28 other style types which can be
set with `style_type_number` (depending on the style type). Check Excel to
find the style that you want. The dialog with the options laid out in numeric
order are shown below:
@image html tables14.png
The default table style in Excel is 'Table Style Medium 9' (highlighted with
a green border in the image above), which is set by default in libxlsxwriter
as:
@code
lxw_table_options options = {
.style_type = LXW_TABLE_STYLE_TYPE_MEDIUM,
.style_type_number = 9,
};
@endcode
You can also turn the table style off by setting it to Light 0:
@code
lxw_table_options options = {
.style_type = LXW_TABLE_STYLE_TYPE_LIGHT,
.style_type_number = 0,
};
@endcode
@image html tables13.png
@subsection ww_tables_name Parameter: name
The `name` parameter is used to set the name of the table. This parameter is
optional and by default tables are named `Table1`, `Table2`, etc. in the
worksheet order that they are added.
@code
lxw_table_options options = {.name = "Sales"};
worksheet_add_table(worksheet, RANGE("B3:G8"), &options);
@endcode
If you override the table name you must ensure that it doesn't clash with an
existing table name and that it follows Excel's requirements for table names,
see the Microsoft Office documentation on [Naming an Excel
Table](https://support.microsoft.com/en-us/office/rename-an-excel-table-fbf49a4f-82a3-43eb-8ba2-44d21233b114).
@subsection ww_tables_total_row Parameter: total_row
The `total_row` parameter can be used to turn on the total row in the last
row of a table. It is distinguished from the other rows by a different
formatting and also with dropdown `SUBTOTAL` functions:
@code
lxw_table_options options = {.total_row = LXW_TRUE};
worksheet_add_table(worksheet, RANGE("B3:G8"), &options);
@endcode
@image html tables9.png
The default total row doesn't have any captions or functions. These must by
specified via the `columns` parameter below.
@subsection ww_tables_columns Parameter: columns
The `columns` parameter can be used to set properties for columns within the
table.
@image html tables7.png
The sub-properties of `lxw_table_column` that can be set are:
- `lxw_table_column.header`
- `lxw_table_column.header_format`
- `lxw_table_column.formula`
- `lxw_table_column.total_string`
- `lxw_table_column.total_function`
- `lxw_table_column.total_value`
- `lxw_table_column.format`
The `columns` parameter should be a NULL terminated array of
`lxw_table_column` pointers. For example to override the default 'Column n'
style table headers:
@code
lxw_table_column col1 = {.header = "Product"};
lxw_table_column col2 = {.header = "Quarter 1"};
lxw_table_column col3 = {.header = "Quarter 2"};
lxw_table_column col4 = {.header = "Quarter 3"};
lxw_table_column col5 = {.header = "Quarter 4"};
lxw_table_column *columns[] = {&col1, &col2, &col3, &col4, &col5, NULL};
lxw_table_options options = {.columns = columns};
worksheet_add_table(worksheet, RANGE("B3:F7"), &options);
@endcode
If you don't wish to specify properties for a specific column you can pass an
empty (but not NULL) struct and the defaults will be applied:
@code
lxw_table_column col1 = {.header = "Product"};
lxw_table_column col2 = {.header = "Quarter 1"};
lxw_table_column col3 = {0}; // Defaults to Column3.
lxw_table_column col4 = {.header = "Quarter 3"};
lxw_table_column col5 = {.header = "Quarter 4"};
@endcode
Column formulas can by applied using the column `formula` property:
@code
lxw_table_column col1 = {.header = "Product"};
lxw_table_column col2 = {.header = "Quarter 1"};
lxw_table_column col3 = {.header = "Quarter 2"};
lxw_table_column col4 = {.header = "Quarter 3"};
lxw_table_column col5 = {.header = "Quarter 4"};
lxw_table_column col6 = {.header = "Year",
.formula = "=SUM(Table8[@[Quarter 1]:[Quarter 4]])"};
lxw_table_column *columns[] = {&col1, &col2, &col3, &col4, &col5, &col6, NULL};
lxw_table_options options = {.columns = columns};
worksheet_add_table(worksheet, RANGE("B3:G7"), &options);
@endcode
@image html tables8.png
The Excel 2007 style `"#This Row"` and Excel 2010 style `"@"` structural
references are supported within the formula. However, other Excel 2010
additions to structural references aren't supported and formulas should
conform to Excel 2007 style formulas. See the Microsoft documentation on
[Using structured references with Excel tables]
(http://office.microsoft.com/en-us/excel-help/using-structured-references-with-excel-tables-HA010155686.aspx)
for details.
As stated above the `total_row` table parameter turns on the "Total" row in
the table but it doesn't populate it with any defaults. Total captions and
functions must be specified via the `columns` property and the `total_string`
and `total_function` sub properties:
@code
lxw_table_column col1 = {.header = "Product",
.total_string = "Totals"};
lxw_table_column col2 = {.header = "Quarter 1",
.total_function = LXW_TABLE_FUNCTION_SUM};
lxw_table_column col3 = {.header = "Quarter 2",
.total_function = LXW_TABLE_FUNCTION_SUM};
lxw_table_column col4 = {.header = "Quarter 3",
.total_function = LXW_TABLE_FUNCTION_SUM};
lxw_table_column col5 = {.header = "Quarter 4",
.total_function = LXW_TABLE_FUNCTION_SUM};
lxw_table_column col6 = {.header = "Year",
.formula = "=SUM(Table10[@[Quarter 1]:[Quarter 4]])",
.total_function = LXW_TABLE_FUNCTION_SUM};
lxw_table_column *columns[] = {&col1, &col2, &col3, &col4, &col5, &col6, NULL};
lxw_table_options options = {.total_row = LXW_TRUE, .columns = columns};
worksheet_add_table(worksheet, RANGE("B3:G8"), &options);
@endcode
The supported totals row `SUBTOTAL` functions are defined in
#lxw_table_total_functions:
- #LXW_TABLE_FUNCTION_AVERAGE
- #LXW_TABLE_FUNCTION_COUNT_NUMS
- #LXW_TABLE_FUNCTION_COUNT
- #LXW_TABLE_FUNCTION_MAX
- #LXW_TABLE_FUNCTION_MIN
- #LXW_TABLE_FUNCTION_STD_DEV
- #LXW_TABLE_FUNCTION_SUM
- #LXW_TABLE_FUNCTION_VAR
User defined functions or formulas aren't supported.
It is also possible to set a calculated value for the `total_function` using
the `total_value` sub property. This is only necessary when creating workbooks
for applications that cannot calculate the value of formulas automatically.
This is similar to setting the `result` property in
`worksheet_write_formula_num()`. See also @ref ww_formulas_results.
Formatting can also be applied to columns using the `format` and to the header
using `header_format` (although you will also need to add it to the data in
the column, see the next section):
@code
lxw_table_column col1 = {.header = "Product",
.total_string = "Totals"};
lxw_table_column col2 = {.header = "Quarter 1",
.total_function = LXW_TABLE_FUNCTION_SUM,
.format = currency_format};
lxw_table_column col3 = {.header = "Quarter 2",
.total_function = LXW_TABLE_FUNCTION_SUM,
.format = currency_format};
lxw_table_column col4 = {.header = "Quarter 3",
.total_function = LXW_TABLE_FUNCTION_SUM,
.format = currency_format};
lxw_table_column col5 = {.header = "Quarter 4",
.total_function = LXW_TABLE_FUNCTION_SUM,
.format = currency_format};
lxw_table_column col6 = {.header = "Year",
.formula = "=SUM(Table13[@[Quarter 1]:[Quarter 4]])",
.total_function = LXW_TABLE_FUNCTION_SUM,
.format = currency_format};
lxw_table_column *columns[] = {&col1, &col2, &col3, &col4, &col5, &col6, NULL};
lxw_table_options options = {.total_row = LXW_TRUE, .columns = columns};
worksheet_add_table(worksheet, RANGE("B3:G8"), &options);
@endcode
@image html tables12.png
Standard libxlsxwriter lxw_format objects are used for this formatting.
However, they should be limited to numerical formats for the columns and
simple formatting like text wrap for the headers. Overriding other table
formatting may produce inconsistent results. You will also need to apply the
same format to any data you write to the column in the table, see the next
section.
@section ww_tables_data Adding data to the table
Once you create a worksheet table you will also need to fill in the data in
the rows and columns. This is done with the standard worksheet write()
functions. For example the data in the examples above was written as follows:
@code
worksheet_write_string(worksheet, 3, 1, "Apples", NULL);
worksheet_write_string(worksheet, 4, 1, "Pears", NULL);
worksheet_write_string(worksheet, 5, 1, "Bananas", NULL);
worksheet_write_string(worksheet, 6, 1, "Oranges", NULL);
worksheet_write_number(worksheet, 3, 2, 10000, format);
worksheet_write_number(worksheet, 4, 2, 2000, format);
worksheet_write_number(worksheet, 5, 2, 6000, format);
worksheet_write_number(worksheet, 6, 2, 500, format);
worksheet_write_number(worksheet, 3, 3, 5000, format);
worksheet_write_number(worksheet, 4, 3, 3000, format);
worksheet_write_number(worksheet, 5, 3, 6000, format);
worksheet_write_number(worksheet, 6, 3, 300, format);
worksheet_write_number(worksheet, 3, 4, 8000, format);
worksheet_write_number(worksheet, 4, 4, 4000, format);
worksheet_write_number(worksheet, 5, 4, 6500, format);
worksheet_write_number(worksheet, 6, 4, 200, format);
worksheet_write_number(worksheet, 3, 5, 6000, format);
worksheet_write_number(worksheet, 4, 5, 5000, format);
worksheet_write_number(worksheet, 5, 5, 6000, format);
worksheet_write_number(worksheet, 6, 5, 700, format);
@endcode
@image html tables2.png
@section ww_tables_Example Example
All of the images shown above are taken from @ref tables.c.
Next: @ref working_with_comments
*/