mirror of
https://github.com/jmcnamara/libxlsxwriter.git
synced 2026-05-15 14:15:54 -06:00
Merge branch 'master' of https://github.com/kruftindustries/libxlsxwriter.git
This commit is contained in:
commit
d6e295f220
507 changed files with 8950 additions and 1199 deletions
1
.indent.pro
vendored
1
.indent.pro
vendored
|
|
@ -109,6 +109,7 @@
|
|||
-T lxw_drawing_object
|
||||
-T lxw_drawing_rel_id
|
||||
-T lxw_error
|
||||
-T lxw_feature_property_bag
|
||||
-T lxw_fill
|
||||
-T lxw_filter_rule
|
||||
-T lxw_filter_rule_obj
|
||||
|
|
|
|||
82
Changes.txt
82
Changes.txt
|
|
@ -3,16 +3,92 @@
|
|||
|
||||
## Information for Packagers
|
||||
|
||||
- This is serial version 1.2.3. This is not a semver version number.
|
||||
- This is serial version 1.2.4. This is not a semver version number.
|
||||
|
||||
- This is shared object library version `libxlsxwriter.so.10`. This should be
|
||||
- This is shared object library version `libxlsxwriter.so.11`. This should be
|
||||
updated automatically via `make` and `cmake` as part of the build process.
|
||||
This version contains ABI changes since the previous release.
|
||||
|
||||
- Please report any downstream patches back upstream to help improve the overall
|
||||
build process.
|
||||
|
||||
|
||||
## 1.2.4 January 2 2026
|
||||
|
||||
- Added support for secondary Y axis in charts. Series can be assigned to a
|
||||
secondary Y axis using an optional fourth parameter to `chart_add_series()`.
|
||||
Secondary axes are accessible via the `chart->x2_axis` and `chart->y2_axis`
|
||||
pointers, and all existing `chart_axis_set_*()` functions work with these
|
||||
secondary axis pointers. The API is backward compatible with existing code.
|
||||
|
||||
- Added support for combined charts via `chart_combine()`. Combined charts
|
||||
allow overlaying two different chart types (e.g., Column + Line, Bar + Line,
|
||||
Area + Column) on the same plot area. For combined charts with secondary
|
||||
axes, set `chart->is_secondary = LXW_TRUE` on the secondary chart.
|
||||
|
||||
- Added `chart_set_series_gap_y2()` and `chart_set_series_overlap_y2()` to set
|
||||
the gap and overlap for series on a secondary Y axis in Bar/Column charts.
|
||||
|
||||
- Added support for Stock charts via `LXW_CHART_STOCK`. Stock charts display
|
||||
High-Low-Close (HLC) or Open-High-Low-Close (OHLC) data. Default series
|
||||
formatting is applied automatically (line with no fill, appropriate markers).
|
||||
Stock charts support hi-low lines, drop lines, and up-down bars.
|
||||
|
||||
- Added `LXW_CHART_MARKER_DOT` marker type used by Stock charts.
|
||||
|
||||
- Added support for gradient fills in chart series, plotarea, and chartarea.
|
||||
New functions: `chart_series_set_gradient()`, `chart_plotarea_set_gradient()`,
|
||||
and `chart_chartarea_set_gradient()`. Supports linear, radial, rectangular,
|
||||
and path gradient types with 2-10 color stops.
|
||||
|
||||
- Added support for textboxes via `worksheet_insert_textbox()` and
|
||||
`worksheet_insert_textbox_opt()`. Textboxes allow inserting text with a
|
||||
rectangular shape into a worksheet. The optional `lxw_textbox_options`
|
||||
struct allows setting width, height, offsets, scale, and description.
|
||||
|
||||
- Added new chart examples:
|
||||
- `chart_stock.c`: Demonstrates stock chart creation with High-Low-Close data.
|
||||
- `chart_pareto.c`: Shows how to create a Pareto chart using combined Column
|
||||
and Line charts with a secondary Y axis.
|
||||
- `chart_gauge.c`: Demonstrates creating a gauge chart by combining Doughnut
|
||||
and Pie charts with custom point colors.
|
||||
- `chart_gradient.c`: Shows how to apply gradient fills to chart series
|
||||
and the plot area.
|
||||
|
||||
- Added `textbox.c` example demonstrating textbox insertion.
|
||||
|
||||
- Added support for sparklines via `worksheet_add_sparkline()`. Sparklines are
|
||||
mini-charts that fit in a single cell to show data trends at a glance. The
|
||||
`lxw_sparkline_options` struct allows configuring:
|
||||
- Sparkline type: line, column, or win/loss
|
||||
- Predefined styles (0-35)
|
||||
- Point markers: high, low, negative, first, last, and all markers
|
||||
- Custom colors for series, markers, and axis
|
||||
- Axis options: min, max, date axis, reverse, show hidden data
|
||||
Added new example:
|
||||
- `sparklines.c`: Demonstrates creating different sparkline types with
|
||||
various options and custom colors.
|
||||
|
||||
- Added support for chart date axis via `chart_axis_set_date_axis()`. This
|
||||
enables date-based X axis on charts with automatic date formatting. Related
|
||||
functions for configuring time units:
|
||||
- `chart_axis_set_major_unit_type()`: Set major time unit (days/months/years)
|
||||
- `chart_axis_set_minor_unit_type()`: Set minor time unit (days/months/years)
|
||||
|
||||
- Added autofit helper utility functions for calculating column widths based
|
||||
on string content:
|
||||
- `lxw_pixel_width()`: Calculate pixel width of a string (Calibri 11 font)
|
||||
- `lxw_autofit_width()`: Calculate column width suitable for
|
||||
`worksheet_set_column()`
|
||||
Note: Excel does not store autofit information in files; these functions
|
||||
help users calculate appropriate column widths programmatically.
|
||||
|
||||
- Added support for inserting checkboxes in worksheet cells via
|
||||
`worksheet_insert_checkbox()`. Checkboxes are a feature of Excel 365
|
||||
from 2024 onwards. They are boolean values displayed as interactive
|
||||
checkboxes in cells. Added new example:
|
||||
- `checkbox.c`: Demonstrates inserting checkboxes with different states.
|
||||
|
||||
|
||||
## 1.2.3 Jun 30 2025
|
||||
|
||||
- Added support for handling dates in the Excel 1904 epoch. See
|
||||
|
|
|
|||
97
build.zig
97
build.zig
|
|
@ -1,16 +1,14 @@
|
|||
const std = @import("std");
|
||||
const zon_version = @import("build.zig.zon").version;
|
||||
|
||||
const xlsxw_version: std.SemanticVersion = .{
|
||||
.major = 1,
|
||||
.minor = 1,
|
||||
.patch = 9,
|
||||
};
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const options: BuildConfig = .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
};
|
||||
const xlsxw_version = std.SemanticVersion.parse(zon_version) catch |err| {
|
||||
std.debug.panic("Error: {s}", .{@errorName(err)});
|
||||
};
|
||||
|
||||
const shared = b.option(bool, "SHARED_LIBRARY", "Build the Shared Library [default: false]") orelse false;
|
||||
const examples = b.option(bool, "BUILD_EXAMPLES", "Build libxlsxwriter examples [default: false]") orelse false;
|
||||
|
|
@ -20,11 +18,15 @@ pub fn build(b: *std.Build) void {
|
|||
const md5 = b.option(bool, "USE_OPENSSL_MD5", "Build libxlsxwriter with the OpenSSL MD5 lib [default: off]") orelse false;
|
||||
const stdtmpfile = b.option(bool, "USE_STANDARD_TMPFILE", "Use the C standard library's tmpfile() [default: off]") orelse false;
|
||||
|
||||
const lib = b.addLibrary(.{
|
||||
const lib = if (shared) b.addSharedLibrary(.{
|
||||
.name = "xlsxwriter",
|
||||
.root_module = createModule(b, options),
|
||||
.linkage = if (shared) .dynamic else .static,
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.version = xlsxw_version,
|
||||
}) else b.addStaticLibrary(.{
|
||||
.name = "xlsxwriter",
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
lib.pie = true;
|
||||
switch (optimize) {
|
||||
|
|
@ -78,7 +80,7 @@ pub fn build(b: *std.Build) void {
|
|||
});
|
||||
}
|
||||
|
||||
const zlib = buildZlib(b, options);
|
||||
const zlib = buildZlib(b, .{ target, optimize });
|
||||
lib.linkLibrary(zlib);
|
||||
lib.installLibraryHeaders(zlib);
|
||||
|
||||
|
|
@ -120,52 +122,42 @@ pub fn build(b: *std.Build) void {
|
|||
// build examples
|
||||
if (examples) {
|
||||
buildExe(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "examples/anatomy.c",
|
||||
});
|
||||
buildExe(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "examples/array_formula.c",
|
||||
});
|
||||
buildExe(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "examples/autofilter.c",
|
||||
});
|
||||
buildExe(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "examples/background.c",
|
||||
});
|
||||
buildExe(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "examples/chart_area.c",
|
||||
});
|
||||
buildExe(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "examples/chart_column.c",
|
||||
});
|
||||
buildExe(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "examples/data_validate.c",
|
||||
});
|
||||
buildExe(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "examples/hello.c",
|
||||
});
|
||||
buildExe(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "examples/watermark.c",
|
||||
});
|
||||
buildExe(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "examples/worksheet_protection.c",
|
||||
});
|
||||
|
|
@ -173,112 +165,93 @@ pub fn build(b: *std.Build) void {
|
|||
// build tests
|
||||
if (tests) {
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/app/test_app.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/chart/test_chart.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/chartsheet/test_chartsheet.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/content_types/test_content_types.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/content_types/test_content_types_write_default.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/content_types/test_content_types_write_override.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/relationships/test_relationships.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/app/test_app_xml_declaration.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/relationships/test_relationships_xml_declaration.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/custom/test_custom_xml_declaration.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/metadata/test_metadata_xml_declaration.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/core/test_core_xml_declaration.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/sst/test_shared_strings.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/workbook/test_workbook.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/xmlwriter/test_xmlwriter.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/table/test_table01.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/table/test_table02.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/table/test_table03.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/table/test_table04.c",
|
||||
});
|
||||
buildTest(b, .{
|
||||
.options = options,
|
||||
.lib = lib,
|
||||
.path = "test/unit/styles/test_styles_write_border.c",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn buildExe(b: *std.Build, info: BuildExec) void {
|
||||
fn buildExe(b: *std.Build, info: BuildInfo) void {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = info.filename(),
|
||||
.root_module = createModule(b, info.options),
|
||||
.optimize = info.lib.root_module.optimize.?,
|
||||
.target = info.lib.root_module.resolved_target.?,
|
||||
});
|
||||
exe.addCSourceFile(.{
|
||||
.file = b.path(info.path),
|
||||
|
|
@ -304,10 +277,11 @@ fn buildExe(b: *std.Build, info: BuildExec) void {
|
|||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
||||
fn buildTest(b: *std.Build, info: BuildExec) void {
|
||||
fn buildTest(b: *std.Build, info: BuildInfo) void {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = info.filename(),
|
||||
.root_module = createModule(b, info.options),
|
||||
.optimize = info.lib.root_module.optimize.?,
|
||||
.target = info.lib.root_module.resolved_target.?,
|
||||
});
|
||||
exe.root_module.addCMacro("TESTING", "");
|
||||
exe.addCSourceFile(.{
|
||||
|
|
@ -319,10 +293,10 @@ fn buildTest(b: *std.Build, info: BuildExec) void {
|
|||
.flags = cflags,
|
||||
});
|
||||
exe.addIncludePath(b.path("test/unit"));
|
||||
exe.linkLibrary(info.lib);
|
||||
for (info.lib.root_module.include_dirs.items) |include| {
|
||||
exe.root_module.include_dirs.append(b.allocator, include) catch @panic("OOM");
|
||||
exe.root_module.include_dirs.append(b.allocator, include) catch {};
|
||||
}
|
||||
exe.linkLibrary(info.lib);
|
||||
exe.linkLibC();
|
||||
b.installArtifact(exe);
|
||||
|
||||
|
|
@ -339,13 +313,6 @@ fn buildTest(b: *std.Build, info: BuildExec) void {
|
|||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
||||
fn createModule(b: *std.Build, options: BuildConfig) *std.Build.Module {
|
||||
return b.createModule(.{
|
||||
.target = options.target,
|
||||
.optimize = options.optimize,
|
||||
});
|
||||
}
|
||||
|
||||
const cflags = &.{
|
||||
"-std=c89",
|
||||
"-Wall",
|
||||
|
|
@ -359,29 +326,25 @@ const minizip_src: []const []const u8 = &.{
|
|||
"third_party/minizip/zip.c",
|
||||
};
|
||||
|
||||
const BuildExec = struct {
|
||||
options: BuildConfig,
|
||||
const BuildInfo = struct {
|
||||
lib: *std.Build.Step.Compile,
|
||||
path: []const u8,
|
||||
|
||||
fn filename(self: BuildExec) []const u8 {
|
||||
fn filename(self: BuildInfo) []const u8 {
|
||||
var split = std.mem.splitSequence(u8, std.fs.path.basename(self.path), ".");
|
||||
return split.first();
|
||||
}
|
||||
};
|
||||
const BuildConfig = struct {
|
||||
target: std.Build.ResolvedTarget,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
};
|
||||
|
||||
fn buildZlib(b: *std.Build, options: BuildConfig) *std.Build.Step.Compile {
|
||||
const libz = b.addLibrary(.{
|
||||
fn buildZlib(b: *std.Build, options: anytype) *std.Build.Step.Compile {
|
||||
const libz = b.addStaticLibrary(.{
|
||||
.name = "z",
|
||||
.root_module = createModule(b, options),
|
||||
.target = options[0],
|
||||
.optimize = options[1],
|
||||
});
|
||||
if (b.lazyDependency("zlib", .{
|
||||
.target = options.target,
|
||||
.optimize = options.optimize,
|
||||
.target = options[0],
|
||||
.optimize = options[1],
|
||||
})) |zlib_path| {
|
||||
libz.addIncludePath(zlib_path.path(""));
|
||||
libz.addCSourceFiles(.{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
.name = .libxlsxwriter,
|
||||
.version = "1.1.9",
|
||||
.fingerprint = 0xa28d9a85f22fad0e,
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.minimum_zig_version = "0.14.0",
|
||||
.dependencies = .{
|
||||
.zlib = .{
|
||||
.url = "git+https://github.com/madler/zlib#v1.3.1",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ cd $SRC/libxlsxwriter
|
|||
printenv
|
||||
|
||||
mkdir -p build
|
||||
cmake -S . -B build -DBUILD_FUZZERS=ON -DBUILD_TESTS=ON && cmake --build build --target install
|
||||
cmake -S . -B build -DBUILD_FUZZERS=ON && cmake --build build --target install
|
||||
|
||||
# Build the corpus using the existing xlsx files in the source
|
||||
mkdir -p corpus
|
||||
|
|
|
|||
368
docs/WINDOWS_BUILD.md
Normal file
368
docs/WINDOWS_BUILD.md
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
# Building libxlsxwriter on Windows with Visual Studio 2026
|
||||
|
||||
This guide provides step-by-step instructions for building libxlsxwriter as a DLL on Windows using Visual Studio 18 2026, with static linking to zlib.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Visual Studio 2026 (VS 18) with C++ Desktop Development workload
|
||||
- CMake 3.15 or later (included with Visual Studio or install separately)
|
||||
- Git for Windows
|
||||
|
||||
## Setting Up the Build Environment
|
||||
|
||||
Before building, you must initialize the Visual C++ environment for your target architecture.
|
||||
|
||||
### For 32-bit Builds
|
||||
|
||||
Open a **Command Prompt** and run:
|
||||
|
||||
```cmd
|
||||
"C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvars32.bat"
|
||||
```
|
||||
|
||||
### For 64-bit Builds
|
||||
|
||||
Open a **Command Prompt** and run:
|
||||
|
||||
```cmd
|
||||
"C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
```
|
||||
|
||||
> **Note:** If you have Visual Studio Professional or Enterprise edition, replace `Community` with `Professional` or `Enterprise` in the path.
|
||||
|
||||
> **Important:** You must use separate command prompt windows for 32-bit and 64-bit builds, or re-run the appropriate vcvars batch file when switching architectures.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
After following these instructions, you will have:
|
||||
|
||||
```
|
||||
C:\dev\
|
||||
├── zlib\
|
||||
│ ├── build32\ # 32-bit zlib static library
|
||||
│ └── build64\ # 64-bit zlib static library
|
||||
└── libxlsxwriter\
|
||||
├── build32\ # 32-bit libxlsxwriter DLL
|
||||
└── build64\ # 64-bit libxlsxwriter DLL
|
||||
```
|
||||
|
||||
## Step 1: Create Working Directory
|
||||
|
||||
Open **Developer Command Prompt for VS 2026** or **PowerShell** and run:
|
||||
|
||||
```cmd
|
||||
mkdir C:\dev
|
||||
cd C:\dev
|
||||
```
|
||||
|
||||
## Step 2: Clone and Build zlib
|
||||
|
||||
### Clone zlib Repository
|
||||
|
||||
```cmd
|
||||
git clone https://github.com/madler/zlib.git
|
||||
cd zlib
|
||||
```
|
||||
|
||||
### Build 32-bit Static zlib Library
|
||||
|
||||
First, set up the 32-bit build environment:
|
||||
|
||||
```cmd
|
||||
"C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvars32.bat"
|
||||
```
|
||||
|
||||
Then build zlib:
|
||||
|
||||
```cmd
|
||||
mkdir build32
|
||||
cd build32
|
||||
|
||||
cmake .. -G "Visual Studio 18 2026" -A Win32 ^
|
||||
-DCMAKE_INSTALL_PREFIX=C:/dev/zlib/install32 ^
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
|
||||
cmake --build . --config Release
|
||||
cmake --install . --config Release
|
||||
|
||||
cd ..
|
||||
```
|
||||
|
||||
### Build 64-bit Static zlib Library
|
||||
|
||||
Set up the 64-bit build environment (open a new command prompt or re-initialize):
|
||||
|
||||
```cmd
|
||||
"C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
```
|
||||
|
||||
Then build zlib:
|
||||
|
||||
```cmd
|
||||
cd C:\dev\zlib
|
||||
mkdir build64
|
||||
cd build64
|
||||
|
||||
cmake .. -G "Visual Studio 18 2026" -A x64 ^
|
||||
-DCMAKE_INSTALL_PREFIX=C:/dev/zlib/install64 ^
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
|
||||
cmake --build . --config Release
|
||||
cmake --install . --config Release
|
||||
|
||||
cd ../..
|
||||
```
|
||||
|
||||
## Step 3: Clone and Build libxlsxwriter
|
||||
|
||||
### Clone libxlsxwriter Repository
|
||||
|
||||
```cmd
|
||||
git clone https://github.com/jmcnamara/libxlsxwriter.git
|
||||
cd libxlsxwriter
|
||||
```
|
||||
|
||||
### Build 32-bit libxlsxwriter DLL
|
||||
|
||||
Set up the 32-bit build environment:
|
||||
|
||||
```cmd
|
||||
"C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvars32.bat"
|
||||
```
|
||||
|
||||
Then build libxlsxwriter:
|
||||
|
||||
```cmd
|
||||
cd C:\dev\libxlsxwriter
|
||||
mkdir build32
|
||||
cd build32
|
||||
|
||||
cmake .. -G "Visual Studio 18 2026" -A Win32 ^
|
||||
-DZLIB_ROOT=C:/dev/zlib/install32 ^
|
||||
-DZLIB_LIBRARY=C:/dev/zlib/install32/lib/zlibstatic.lib ^
|
||||
-DZLIB_INCLUDE_DIR=C:/dev/zlib/install32/include ^
|
||||
-DBUILD_SHARED_LIBS=ON ^
|
||||
-DUSE_STATIC_MSVC_RUNTIME=OFF
|
||||
|
||||
cmake --build . --config Release
|
||||
|
||||
cd ..
|
||||
```
|
||||
|
||||
The 32-bit DLL will be located at: `build32\Release\xlsxwriter.dll`
|
||||
|
||||
### Build 64-bit libxlsxwriter DLL
|
||||
|
||||
Set up the 64-bit build environment (open a new command prompt or re-initialize):
|
||||
|
||||
```cmd
|
||||
"C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
```
|
||||
|
||||
Then build libxlsxwriter:
|
||||
|
||||
```cmd
|
||||
cd C:\dev\libxlsxwriter
|
||||
mkdir build64
|
||||
cd build64
|
||||
|
||||
cmake .. -G "Visual Studio 18 2026" -A x64 ^
|
||||
-DZLIB_ROOT=C:/dev/zlib/install64 ^
|
||||
-DZLIB_LIBRARY=C:/dev/zlib/install64/lib/zlibstatic.lib ^
|
||||
-DZLIB_INCLUDE_DIR=C:/dev/zlib/install64/include ^
|
||||
-DBUILD_SHARED_LIBS=ON ^
|
||||
-DUSE_STATIC_MSVC_RUNTIME=OFF
|
||||
|
||||
cmake --build . --config Release
|
||||
|
||||
cd ..
|
||||
```
|
||||
|
||||
The 64-bit DLL will be located at: `build64\Release\xlsxwriter.dll`
|
||||
|
||||
## Step 4: Verify Build Output
|
||||
|
||||
After successful builds, you should have the following files:
|
||||
|
||||
### 32-bit Build
|
||||
```
|
||||
libxlsxwriter\build32\Release\
|
||||
├── xlsxwriter.dll # Dynamic library
|
||||
├── xlsxwriter.lib # Import library for linking
|
||||
└── xlsxwriter.pdb # Debug symbols (optional)
|
||||
```
|
||||
|
||||
### 64-bit Build
|
||||
```
|
||||
libxlsxwriter\build64\Release\
|
||||
├── xlsxwriter.dll # Dynamic library
|
||||
├── xlsxwriter.lib # Import library for linking
|
||||
└── xlsxwriter.pdb # Debug symbols (optional)
|
||||
```
|
||||
|
||||
## Optional: Build Static Library with Static MSVC Runtime
|
||||
|
||||
If you prefer a fully static build (no C runtime DLL dependency), use these options:
|
||||
|
||||
```cmd
|
||||
cmake .. -G "Visual Studio 18 2026" -A x64 ^
|
||||
-DZLIB_ROOT=C:/dev/zlib/install64 ^
|
||||
-DZLIB_LIBRARY=C:/dev/zlib/install64/lib/zlibstatic.lib ^
|
||||
-DZLIB_INCLUDE_DIR=C:/dev/zlib/install64/include ^
|
||||
-DBUILD_SHARED_LIBS=OFF ^
|
||||
-DUSE_STATIC_MSVC_RUNTIME=ON
|
||||
|
||||
cmake --build . --config Release
|
||||
```
|
||||
|
||||
## Optional: Build Debug Configuration
|
||||
|
||||
To build debug versions, replace `Release` with `Debug`:
|
||||
|
||||
```cmd
|
||||
cmake --build . --config Debug
|
||||
```
|
||||
|
||||
## Using the Library in Your Project
|
||||
|
||||
### For DLL Builds
|
||||
|
||||
1. Copy `xlsxwriter.dll` to your application directory or system PATH
|
||||
2. Link against `xlsxwriter.lib` (import library)
|
||||
3. Include headers from `libxlsxwriter\include\`
|
||||
|
||||
### CMake Integration
|
||||
|
||||
```cmake
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
add_subdirectory(path/to/libxlsxwriter)
|
||||
|
||||
target_link_libraries(your_app PRIVATE xlsxwriter)
|
||||
```
|
||||
|
||||
### Visual Studio Project Settings
|
||||
|
||||
1. Add to **Additional Include Directories**: `C:\dev\libxlsxwriter\include`
|
||||
2. Add to **Additional Library Directories**: `C:\dev\libxlsxwriter\build64\Release`
|
||||
3. Add to **Additional Dependencies**: `xlsxwriter.lib`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### CMake Cannot Find zlib
|
||||
|
||||
Ensure the paths are correct and use forward slashes (`/`) in CMake paths:
|
||||
```cmd
|
||||
-DZLIB_ROOT=C:/dev/zlib/install64
|
||||
```
|
||||
|
||||
### Linker Errors with zlib
|
||||
|
||||
If you get unresolved external symbols for zlib functions, verify:
|
||||
- You're linking against `zlibstatic.lib` (not `zlib.lib`)
|
||||
- The architecture matches (Win32 with Win32, x64 with x64)
|
||||
|
||||
### Missing vcruntime DLLs
|
||||
|
||||
If the DLL requires Visual C++ runtime, either:
|
||||
- Install the Visual C++ Redistributable on target machines
|
||||
- Build with `-DUSE_STATIC_MSVC_RUNTIME=ON` for static runtime
|
||||
|
||||
### Build Errors with Examples
|
||||
|
||||
To skip building examples:
|
||||
```cmd
|
||||
cmake .. -DBUILD_EXAMPLES=OFF ...
|
||||
```
|
||||
|
||||
## Complete Build Script
|
||||
|
||||
Save as `build_all.bat`:
|
||||
|
||||
```batch
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
set DEV_DIR=C:\dev
|
||||
set GENERATOR="Visual Studio 18 2026"
|
||||
set VCVARS_PATH=C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build
|
||||
|
||||
:: Create dev directory
|
||||
mkdir %DEV_DIR% 2>nul
|
||||
cd /d %DEV_DIR%
|
||||
|
||||
:: Clone zlib
|
||||
echo === Cloning zlib ===
|
||||
git clone https://github.com/madler/zlib.git
|
||||
|
||||
:: Clone libxlsxwriter
|
||||
echo === Cloning libxlsxwriter ===
|
||||
git clone https://github.com/jmcnamara/libxlsxwriter.git
|
||||
|
||||
:: ============================================================
|
||||
:: Build 32-bit versions
|
||||
:: ============================================================
|
||||
echo === Setting up 32-bit build environment ===
|
||||
call "%VCVARS_PATH%\vcvars32.bat"
|
||||
|
||||
echo === Building 32-bit zlib ===
|
||||
cd /d %DEV_DIR%\zlib
|
||||
mkdir build32 2>nul
|
||||
cd build32
|
||||
cmake .. -G %GENERATOR% -A Win32 -DCMAKE_INSTALL_PREFIX=%DEV_DIR%/zlib/install32 -DBUILD_SHARED_LIBS=OFF
|
||||
cmake --build . --config Release
|
||||
cmake --install . --config Release
|
||||
|
||||
echo === Building 32-bit libxlsxwriter ===
|
||||
cd /d %DEV_DIR%\libxlsxwriter
|
||||
mkdir build32 2>nul
|
||||
cd build32
|
||||
cmake .. -G %GENERATOR% -A Win32 ^
|
||||
-DZLIB_ROOT=%DEV_DIR%/zlib/install32 ^
|
||||
-DZLIB_LIBRARY=%DEV_DIR%/zlib/install32/lib/zlibstatic.lib ^
|
||||
-DZLIB_INCLUDE_DIR=%DEV_DIR%/zlib/install32/include ^
|
||||
-DBUILD_SHARED_LIBS=ON
|
||||
cmake --build . --config Release
|
||||
|
||||
:: ============================================================
|
||||
:: Build 64-bit versions
|
||||
:: ============================================================
|
||||
echo === Setting up 64-bit build environment ===
|
||||
call "%VCVARS_PATH%\vcvars64.bat"
|
||||
|
||||
echo === Building 64-bit zlib ===
|
||||
cd /d %DEV_DIR%\zlib
|
||||
mkdir build64 2>nul
|
||||
cd build64
|
||||
cmake .. -G %GENERATOR% -A x64 -DCMAKE_INSTALL_PREFIX=%DEV_DIR%/zlib/install64 -DBUILD_SHARED_LIBS=OFF
|
||||
cmake --build . --config Release
|
||||
cmake --install . --config Release
|
||||
|
||||
echo === Building 64-bit libxlsxwriter ===
|
||||
cd /d %DEV_DIR%\libxlsxwriter
|
||||
mkdir build64 2>nul
|
||||
cd build64
|
||||
cmake .. -G %GENERATOR% -A x64 ^
|
||||
-DZLIB_ROOT=%DEV_DIR%/zlib/install64 ^
|
||||
-DZLIB_LIBRARY=%DEV_DIR%/zlib/install64/lib/zlibstatic.lib ^
|
||||
-DZLIB_INCLUDE_DIR=%DEV_DIR%/zlib/install64/include ^
|
||||
-DBUILD_SHARED_LIBS=ON
|
||||
cmake --build . --config Release
|
||||
|
||||
:: ============================================================
|
||||
:: Done
|
||||
:: ============================================================
|
||||
echo.
|
||||
echo === Build Complete ===
|
||||
echo 32-bit DLL: %DEV_DIR%\libxlsxwriter\build32\Release\xlsxwriter.dll
|
||||
echo 64-bit DLL: %DEV_DIR%\libxlsxwriter\build64\Release\xlsxwriter.dll
|
||||
echo.
|
||||
|
||||
pause
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [libxlsxwriter Documentation](https://libxlsxwriter.github.io/)
|
||||
- [CMake Documentation](https://cmake.org/documentation/)
|
||||
- [zlib Home Page](https://zlib.net/)
|
||||
|
|
@ -1294,17 +1294,7 @@ The chart functions that support #lxw_chart_layout are:
|
|||
|
||||
@section ww_charts_limitations Chart Limitations
|
||||
|
||||
The following chart features aren't currently supported in libxlsxwriter but
|
||||
will be in time. See the [GitHub Chart Feature Requests][1].
|
||||
|
||||
[1]: https://github.com/jmcnamara/libxlsxwriter/issues
|
||||
|
||||
- Secondary axis.
|
||||
- Combined charts.
|
||||
- Chartsheets.
|
||||
|
||||
If required these features are all available in the Perl and Python versions
|
||||
of this library.
|
||||
All chart features in the original Excel specification are supported.
|
||||
|
||||
|
||||
Next: @ref working_with_object_positioning
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ int main() {
|
|||
/* Configure the chart. In simplest case we just add some value data
|
||||
* series. The NULL categories will default to 1 to 5 like in Excel.
|
||||
*/
|
||||
chart_add_series(chart, NULL, "Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
|
||||
lxw_chart_font font = {.bold = LXW_EXPLICIT_FALSE, .color = LXW_COLOR_BLUE};
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@ int main() {
|
|||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_AREA);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add a second series but leave the categories and values undefined. They
|
||||
* can be defined later using the alternative syntax shown below. */
|
||||
series = chart_add_series(chart, NULL, NULL);
|
||||
series = chart_add_series(chart, NULL, NULL, 0);
|
||||
|
||||
/* Configure the series using a syntax that is easier to define programmatically. */
|
||||
chart_series_set_categories(series, "Sheet1", 1, 0, 6, 0); /* "=Sheet1!$A$2:$A$7" */
|
||||
|
|
@ -87,13 +87,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_AREA_STACKED);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
@ -116,13 +116,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_AREA_STACKED_PERCENT);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@ int main() {
|
|||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_BAR);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add a second series but leave the categories and values undefined. They
|
||||
* can be defined later using the alternative syntax shown below. */
|
||||
series = chart_add_series(chart, NULL, NULL);
|
||||
series = chart_add_series(chart, NULL, NULL, 0);
|
||||
|
||||
/* Configure the series using a syntax that is easier to define programmatically. */
|
||||
chart_series_set_categories(series, "Sheet1", 1, 0, 6, 0); /* "=Sheet1!$A$2:$A$7" */
|
||||
|
|
@ -87,13 +87,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_BAR_STACKED);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
@ -116,13 +116,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_BAR_STACKED_PERCENT);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
|
|||
|
|
@ -71,15 +71,15 @@ int main() {
|
|||
*/
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$2:$B$6",
|
||||
"=Sheet1!$C$2:$C$6");
|
||||
"=Sheet1!$C$2:$C$6", 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$2:$B$6",
|
||||
"=Sheet1!$D$2:$D$6");
|
||||
"=Sheet1!$D$2:$D$6", 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$2:$B$6",
|
||||
"=Sheet1!$E$2:$E$6");
|
||||
"=Sheet1!$E$2:$E$6", 0);
|
||||
|
||||
/* Set an Excel chart style. */
|
||||
chart_set_style(chart, 37);
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@ int main() {
|
|||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add a second series but leave the categories and values undefined. They
|
||||
* can be defined later using the alternative syntax shown below. */
|
||||
series = chart_add_series(chart, NULL, NULL);
|
||||
series = chart_add_series(chart, NULL, NULL, 0);
|
||||
|
||||
/* Configure the series using a syntax that is easier to define programmatically. */
|
||||
chart_series_set_categories(series, "Sheet1", 1, 0, 6, 0); /* "=Sheet1!$A$2:$A$7" */
|
||||
|
|
@ -87,13 +87,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_COLUMN_STACKED);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
@ -116,13 +116,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_COLUMN_STACKED_PERCENT);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
|
|||
146
examples/chart_combined.c
Normal file
146
examples/chart_combined.c
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* An example of creating combined charts using the libxlsxwriter library.
|
||||
*
|
||||
* A combined chart is one that shows two chart types, such as a column chart
|
||||
* combined with a line chart. They can share the same Y axis or have a
|
||||
* secondary Y axis.
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
/*
|
||||
* Write some data to the worksheet.
|
||||
*/
|
||||
void write_worksheet_data(lxw_worksheet *worksheet, lxw_format *bold) {
|
||||
|
||||
int row, col;
|
||||
uint8_t data[6][3] = {
|
||||
/* Three columns of data. */
|
||||
{2, 10, 30},
|
||||
{3, 40, 60},
|
||||
{4, 50, 70},
|
||||
{5, 20, 50},
|
||||
{6, 10, 40},
|
||||
{7, 50, 30}
|
||||
};
|
||||
|
||||
worksheet_write_string(worksheet, CELL("A1"), "Number", bold);
|
||||
worksheet_write_string(worksheet, CELL("B1"), "Batch 1", bold);
|
||||
worksheet_write_string(worksheet, CELL("C1"), "Batch 2", bold);
|
||||
|
||||
for (row = 0; row < 6; row++)
|
||||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row + 1, col, data[row][col], NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a worksheet with combined chart examples.
|
||||
*/
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("chart_combined.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
lxw_chart_series *series;
|
||||
|
||||
/* Add a bold format to use to highlight the header cells. */
|
||||
lxw_format *bold = workbook_add_format(workbook);
|
||||
format_set_bold(bold);
|
||||
|
||||
/* Write some data for the chart. */
|
||||
write_worksheet_data(worksheet, bold);
|
||||
|
||||
|
||||
/*
|
||||
* Chart 1. Create a combined column and line chart with shared Y axis.
|
||||
*
|
||||
* In this example we will create a combined column and line chart.
|
||||
* They will share the same X and Y axes.
|
||||
*/
|
||||
|
||||
/* Create a column chart - this will be the primary chart. */
|
||||
lxw_chart *column_chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
|
||||
|
||||
/* Add the first series to the primary chart. */
|
||||
series = chart_add_series(column_chart,
|
||||
"=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7",
|
||||
0); /* Primary Y axis */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Create a line chart - this will be the secondary (combined) chart. */
|
||||
lxw_chart *line_chart = workbook_add_chart(workbook, LXW_CHART_LINE);
|
||||
|
||||
/* Add the first series to the secondary chart. */
|
||||
series = chart_add_series(line_chart,
|
||||
"=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$C$2:$C$7",
|
||||
0); /* Primary Y axis (shared with column chart) */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
||||
/* Combine the charts. The line chart is overlaid on the column chart. */
|
||||
chart_combine(column_chart, line_chart);
|
||||
|
||||
/* Add a chart title and axis labels. Note: these are set on the
|
||||
* primary chart. */
|
||||
chart_title_set_name(column_chart, "Combined chart - same Y axis");
|
||||
chart_axis_set_name(column_chart->x_axis, "Test number");
|
||||
chart_axis_set_name(column_chart->y_axis, "Sample length (mm)");
|
||||
|
||||
/* Insert the chart into the worksheet. */
|
||||
worksheet_insert_chart(worksheet, CELL("E2"), column_chart);
|
||||
|
||||
|
||||
/*
|
||||
* Chart 2. Create a combined column and line chart with secondary Y axis.
|
||||
*
|
||||
* In this example we create a similar combined column and line chart
|
||||
* except that the line chart has a secondary Y axis on the right side.
|
||||
*/
|
||||
|
||||
/* Create a column chart - this will be the primary chart. */
|
||||
lxw_chart *column_chart2 = workbook_add_chart(workbook, LXW_CHART_COLUMN);
|
||||
|
||||
/* Add the first series to the primary chart. */
|
||||
series = chart_add_series(column_chart2,
|
||||
"=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7",
|
||||
0); /* Primary Y axis */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Create a line chart - this will be the secondary (combined) chart. */
|
||||
lxw_chart *line_chart2 = workbook_add_chart(workbook, LXW_CHART_LINE);
|
||||
|
||||
/* Add the first series to the secondary chart.
|
||||
*
|
||||
* Set y2_axis = 1 to place this series on the secondary Y axis.
|
||||
* This tells the library to:
|
||||
* 1. Use secondary axis IDs for this series
|
||||
* 2. Write the secondary axis elements (Y2 on right, X2 hidden)
|
||||
*/
|
||||
series = chart_add_series(line_chart2,
|
||||
"=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$C$2:$C$7",
|
||||
1); /* y2_axis = 1: Use secondary Y axis */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
||||
/* Combine the charts. */
|
||||
chart_combine(column_chart2, line_chart2);
|
||||
|
||||
/* Add a chart title and axis labels. */
|
||||
chart_title_set_name(column_chart2, "Combined chart - secondary Y axis");
|
||||
chart_axis_set_name(column_chart2->x_axis, "Test number");
|
||||
chart_axis_set_name(column_chart2->y_axis, "Sample length (mm)");
|
||||
|
||||
/* Configure the secondary Y axis (accessed via the primary chart).
|
||||
* The secondary Y axis appears on the right side of the chart. */
|
||||
chart_axis_set_name(column_chart2->y2_axis, "Target length (mm)");
|
||||
|
||||
/* Insert the chart into the worksheet. */
|
||||
worksheet_insert_chart(worksheet, CELL("E18"), column_chart2);
|
||||
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ int main() {
|
|||
|
||||
/* Add a data series to the chart. */
|
||||
lxw_chart_series *series = chart_add_series(chart, "=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7");
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Add the series data labels. */
|
||||
chart_series_set_labels(series);
|
||||
|
|
@ -81,7 +81,7 @@ int main() {
|
|||
|
||||
/* Add a data series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7");
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Add the series data labels. */
|
||||
chart_series_set_labels(series);
|
||||
|
|
@ -106,7 +106,7 @@ int main() {
|
|||
|
||||
/* Add a data series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7");
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Add the series data labels. */
|
||||
chart_series_set_labels(series);
|
||||
|
|
@ -131,7 +131,7 @@ int main() {
|
|||
|
||||
/* Add a data series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7");
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Add the series data labels. */
|
||||
chart_series_set_labels(series);
|
||||
|
|
@ -160,7 +160,7 @@ int main() {
|
|||
|
||||
/* Add a data series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7");
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Add the series data labels. */
|
||||
chart_series_set_labels(series);
|
||||
|
|
@ -204,7 +204,7 @@ int main() {
|
|||
|
||||
/* Add a data series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7");
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Add the series data labels. */
|
||||
chart_series_set_labels(series);
|
||||
|
|
@ -248,7 +248,7 @@ int main() {
|
|||
|
||||
/* Add a data series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7");
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
lxw_chart_font font2 = {.color = LXW_COLOR_RED};
|
||||
|
||||
|
|
@ -296,7 +296,7 @@ int main() {
|
|||
|
||||
/* Add a data series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7");
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Add the series data labels. */
|
||||
chart_series_set_labels(series);
|
||||
|
|
@ -339,7 +339,7 @@ int main() {
|
|||
|
||||
/* Add a data series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7");
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Add the series data labels. */
|
||||
chart_series_set_labels(series);
|
||||
|
|
|
|||
|
|
@ -56,14 +56,14 @@ int main() {
|
|||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add a second series but leave the categories and values undefined. They
|
||||
* can be defined later using the alternative syntax shown below. */
|
||||
series = chart_add_series(chart, NULL, NULL);
|
||||
series = chart_add_series(chart, NULL, NULL, 0);
|
||||
|
||||
/* Configure the series using a syntax that is easier to define programmatically. */
|
||||
chart_series_set_categories(series, "Sheet1", 1, 0, 6, 0); /* "=Sheet1!$A$2:$A$7" */
|
||||
|
|
@ -88,13 +88,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ int main() {
|
|||
chart_title_set_name(chart, "Chart with High-Low Lines");
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Add high-low lines to the chart. */
|
||||
chart_set_high_low_lines(chart, NULL);
|
||||
|
|
@ -79,8 +79,8 @@ int main() {
|
|||
chart_title_set_name(chart, "Chart with Drop Lines");
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Add drop lines to the chart. */
|
||||
chart_set_drop_lines(chart, NULL);
|
||||
|
|
@ -98,8 +98,8 @@ int main() {
|
|||
chart_title_set_name(chart, "Chart with Up-Down bars");
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Add Up-Down bars to the chart. */
|
||||
chart_set_up_down_bars(chart);
|
||||
|
|
@ -117,8 +117,8 @@ int main() {
|
|||
chart_title_set_name(chart, "Chart with Up-Down bars");
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Add Up-Down bars to the chart, with formatting. */
|
||||
lxw_chart_line line = {.color = LXW_COLOR_BLACK};
|
||||
|
|
@ -140,8 +140,8 @@ int main() {
|
|||
chart_title_set_name(chart, "Chart with Data Labels and Markers");
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
chart_add_series( chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
chart_add_series( chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Add series markers. */
|
||||
chart_series_set_marker_type(series, LXW_CHART_MARKER_CIRCLE);
|
||||
|
|
@ -162,8 +162,8 @@ int main() {
|
|||
chart_title_set_name(chart, "Chart with Error Bars");
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
chart_add_series( chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
chart_add_series( chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Add error bars to show Standard Error. */
|
||||
chart_series_set_error_bars(series->y_error_bars,
|
||||
|
|
@ -185,8 +185,8 @@ int main() {
|
|||
chart_title_set_name(chart, "Chart with a Trendline");
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
chart_add_series( chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
chart_add_series( chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Add a polynomial trendline. */
|
||||
lxw_chart_line poly_line = {.color = LXW_COLOR_GRAY,
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_DOUGHNUT);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "Doughnut sales data");
|
||||
|
|
@ -75,7 +75,7 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_DOUGHNUT);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "Doughnut sales data");
|
||||
|
|
@ -112,7 +112,7 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_DOUGHNUT);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "Doughnut sales data");
|
||||
|
|
@ -135,7 +135,7 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_DOUGHNUT);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "Doughnut sales data");
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ int main() {
|
|||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE);
|
||||
|
||||
/* Configure the chart. */
|
||||
chart_add_series(chart, NULL, "Sheet1!$A$1:$A$6");
|
||||
chart_add_series(chart, NULL, "Sheet1!$A$1:$A$6", 0);
|
||||
|
||||
/* Create some fonts to use in the chart. */
|
||||
lxw_chart_font font1 = {.name = "Calibri", .color = LXW_COLOR_BLUE};
|
||||
|
|
|
|||
105
examples/chart_gauge.c
Normal file
105
examples/chart_gauge.c
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* An example of creating a Gauge Chart in Excel with libxlsxwriter.
|
||||
*
|
||||
* A Gauge Chart isn't a native chart type in Excel. It is constructed by
|
||||
* combining a doughnut chart and a pie chart and by using some non-filled
|
||||
* elements. This example follows the following online example of how to create
|
||||
* a Gauge Chart in Excel: https://www.excel-easy.com/examples/gauge-chart.html
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("chart_gauge.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
lxw_chart_series *series;
|
||||
|
||||
/* Add some data for the Doughnut and Pie charts. This is set up so the
|
||||
* gauge goes from 0-100. It is initially set at 75%. */
|
||||
worksheet_write_string(worksheet, 1, 7, "Donut", NULL);
|
||||
worksheet_write_number(worksheet, 2, 7, 25, NULL);
|
||||
worksheet_write_number(worksheet, 3, 7, 50, NULL);
|
||||
worksheet_write_number(worksheet, 4, 7, 25, NULL);
|
||||
worksheet_write_number(worksheet, 5, 7, 100, NULL);
|
||||
|
||||
worksheet_write_string(worksheet, 1, 8, "Pie", NULL);
|
||||
worksheet_write_number(worksheet, 2, 8, 75, NULL);
|
||||
worksheet_write_number(worksheet, 3, 8, 1, NULL);
|
||||
worksheet_write_formula(worksheet, 4, 8, "=200-I4-I3", NULL);
|
||||
|
||||
/* Create a doughnut chart for the background of the gauge. */
|
||||
lxw_chart *chart_doughnut = workbook_add_chart(workbook, LXW_CHART_DOUGHNUT);
|
||||
|
||||
/* Add the doughnut chart series with colors for the segments. */
|
||||
series = chart_add_series(chart_doughnut,
|
||||
NULL, "=Sheet1!$H$3:$H$6", 0);
|
||||
chart_series_set_name(series, "=Sheet1!$H$2");
|
||||
|
||||
/* Create fills for the doughnut segments: green, yellow, red, and no fill. */
|
||||
lxw_chart_fill green_fill = {.color = 0x00B050};
|
||||
lxw_chart_fill yellow_fill = {.color = 0xFFFF00};
|
||||
lxw_chart_fill red_fill = {.color = 0xFF0000};
|
||||
lxw_chart_fill no_fill = {.none = LXW_TRUE};
|
||||
|
||||
lxw_chart_point green_point = {.fill = &green_fill};
|
||||
lxw_chart_point yellow_point = {.fill = &yellow_fill};
|
||||
lxw_chart_point red_point = {.fill = &red_fill};
|
||||
lxw_chart_point empty_point = {.fill = &no_fill};
|
||||
|
||||
lxw_chart_point *doughnut_points[] = {&green_point,
|
||||
&yellow_point,
|
||||
&red_point,
|
||||
&empty_point,
|
||||
NULL};
|
||||
|
||||
chart_series_set_points(series, doughnut_points);
|
||||
|
||||
/* Rotate the doughnut chart so the gauge segments are above the horizontal. */
|
||||
chart_set_rotation(chart_doughnut, 270);
|
||||
|
||||
/* Turn off the chart legend. */
|
||||
chart_legend_set_position(chart_doughnut, LXW_CHART_LEGEND_NONE);
|
||||
|
||||
/* Turn off the chart fill and border. */
|
||||
lxw_chart_fill chart_no_fill = {.none = LXW_TRUE};
|
||||
lxw_chart_line chart_no_line = {.none = LXW_TRUE};
|
||||
chart_chartarea_set_fill(chart_doughnut, &chart_no_fill);
|
||||
chart_chartarea_set_line(chart_doughnut, &chart_no_line);
|
||||
|
||||
/* Create a pie chart for the needle of the gauge. */
|
||||
lxw_chart *chart_pie = workbook_add_chart(workbook, LXW_CHART_PIE);
|
||||
|
||||
/* Add the pie chart series for the needle. */
|
||||
series = chart_add_series(chart_pie,
|
||||
NULL, "=Sheet1!$I$3:$I$6", 0);
|
||||
chart_series_set_name(series, "=Sheet1!$I$2");
|
||||
|
||||
/* Create fills for the pie segments: no fill, black (needle), no fill. */
|
||||
lxw_chart_fill black_fill = {.color = 0x000000};
|
||||
|
||||
lxw_chart_point pie_empty1 = {.fill = &no_fill};
|
||||
lxw_chart_point pie_needle = {.fill = &black_fill};
|
||||
lxw_chart_point pie_empty2 = {.fill = &no_fill};
|
||||
|
||||
lxw_chart_point *pie_points[] = {&pie_empty1,
|
||||
&pie_needle,
|
||||
&pie_empty2,
|
||||
NULL};
|
||||
|
||||
chart_series_set_points(series, pie_points);
|
||||
|
||||
/* Rotate the pie chart to align the needle with the doughnut gauge. */
|
||||
chart_set_rotation(chart_pie, 270);
|
||||
|
||||
/* Combine the doughnut and pie charts. */
|
||||
chart_combine(chart_doughnut, chart_pie);
|
||||
|
||||
/* Insert the combined chart into the worksheet. */
|
||||
worksheet_insert_chart(worksheet, CELL("A1"), chart_doughnut);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
97
examples/chart_gradient.c
Normal file
97
examples/chart_gradient.c
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* An example of creating an Excel column chart with gradient fills using
|
||||
* libxlsxwriter.
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("chart_gradient.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
lxw_chart_series *series;
|
||||
|
||||
/* Add a bold format for the headers. */
|
||||
lxw_format *bold = workbook_add_format(workbook);
|
||||
format_set_bold(bold);
|
||||
|
||||
/* Write the worksheet data that the chart will refer to. */
|
||||
worksheet_write_string(worksheet, 0, 0, "Number", bold);
|
||||
worksheet_write_string(worksheet, 0, 1, "Batch 1", bold);
|
||||
worksheet_write_string(worksheet, 0, 2, "Batch 2", bold);
|
||||
|
||||
worksheet_write_number(worksheet, 1, 0, 2, NULL);
|
||||
worksheet_write_number(worksheet, 2, 0, 3, NULL);
|
||||
worksheet_write_number(worksheet, 3, 0, 4, NULL);
|
||||
worksheet_write_number(worksheet, 4, 0, 5, NULL);
|
||||
worksheet_write_number(worksheet, 5, 0, 6, NULL);
|
||||
worksheet_write_number(worksheet, 6, 0, 7, NULL);
|
||||
|
||||
worksheet_write_number(worksheet, 1, 1, 10, NULL);
|
||||
worksheet_write_number(worksheet, 2, 1, 40, NULL);
|
||||
worksheet_write_number(worksheet, 3, 1, 50, NULL);
|
||||
worksheet_write_number(worksheet, 4, 1, 20, NULL);
|
||||
worksheet_write_number(worksheet, 5, 1, 10, NULL);
|
||||
worksheet_write_number(worksheet, 6, 1, 50, NULL);
|
||||
|
||||
worksheet_write_number(worksheet, 1, 2, 30, NULL);
|
||||
worksheet_write_number(worksheet, 2, 2, 60, NULL);
|
||||
worksheet_write_number(worksheet, 3, 2, 70, NULL);
|
||||
worksheet_write_number(worksheet, 4, 2, 50, NULL);
|
||||
worksheet_write_number(worksheet, 5, 2, 40, NULL);
|
||||
worksheet_write_number(worksheet, 6, 2, 30, NULL);
|
||||
|
||||
/* Create a column chart. */
|
||||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
|
||||
|
||||
/* Configure the first series with a gradient fill. */
|
||||
series = chart_add_series(chart,
|
||||
"=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Set gradient: dark red to light red. */
|
||||
lxw_chart_gradient_fill gradient1 = {
|
||||
.type = LXW_CHART_GRADIENT_FILL_LINEAR,
|
||||
.colors = {0x963735, 0xF1DCDB},
|
||||
.num_stops = 2,
|
||||
};
|
||||
chart_series_set_gradient(series, &gradient1);
|
||||
|
||||
/* Configure the second series with a gradient fill. */
|
||||
series = chart_add_series(chart,
|
||||
"=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$C$2:$C$7", 0);
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
||||
/* Set gradient: dark orange to light orange. */
|
||||
lxw_chart_gradient_fill gradient2 = {
|
||||
.type = LXW_CHART_GRADIENT_FILL_LINEAR,
|
||||
.colors = {0xE36C0A, 0xFCEADA},
|
||||
.num_stops = 2,
|
||||
};
|
||||
chart_series_set_gradient(series, &gradient2);
|
||||
|
||||
/* Set a gradient fill for the plotarea. */
|
||||
lxw_chart_gradient_fill plotarea_gradient = {
|
||||
.type = LXW_CHART_GRADIENT_FILL_LINEAR,
|
||||
.colors = {0xFFEFD1, 0xF0EBD5, 0xB69F66},
|
||||
.num_stops = 3,
|
||||
};
|
||||
chart_plotarea_set_gradient(chart, &plotarea_gradient);
|
||||
|
||||
/* Add axis labels. */
|
||||
chart_axis_set_name(chart->x_axis, "Test number");
|
||||
chart_axis_set_name(chart->y_axis, "Sample length (mm)");
|
||||
|
||||
/* Turn off the chart legend. */
|
||||
chart_legend_set_position(chart, LXW_CHART_LEGEND_NONE);
|
||||
|
||||
/* Insert the chart into the worksheet. */
|
||||
worksheet_insert_chart(worksheet, CELL("E2"), chart);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
|
|
@ -55,14 +55,14 @@ int main() {
|
|||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add a second series but leave the categories and values undefined. They
|
||||
* can be defined later using the alternative syntax shown below. */
|
||||
series = chart_add_series(chart, NULL, NULL);
|
||||
series = chart_add_series(chart, NULL, NULL, 0);
|
||||
|
||||
/* Configure the series using a syntax that is easier to define programmatically. */
|
||||
chart_series_set_categories(series, "Sheet1", 1, 0, 6, 0); /* "=Sheet1!$A$2:$A$7" */
|
||||
|
|
@ -87,13 +87,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_LINE_STACKED);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
@ -116,13 +116,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_LINE_STACKED_PERCENT);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
|
|||
102
examples/chart_pareto.c
Normal file
102
examples/chart_pareto.c
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* An example of creating a Pareto chart with libxlsxwriter.
|
||||
*
|
||||
* A Pareto chart is a type of chart that combines a column chart with a line
|
||||
* chart. The columns represent individual values in descending order, and the
|
||||
* line represents the cumulative percentage.
|
||||
*
|
||||
* This example uses combined charts with a secondary Y axis.
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("chart_pareto.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Add formats for the worksheet data. */
|
||||
lxw_format *bold = workbook_add_format(workbook);
|
||||
format_set_bold(bold);
|
||||
|
||||
lxw_format *percent_format = workbook_add_format(workbook);
|
||||
format_set_num_format(percent_format, "0.0%");
|
||||
|
||||
/* Widen the columns for visibility. */
|
||||
worksheet_set_column(worksheet, COLS("A:A"), 15, NULL);
|
||||
worksheet_set_column(worksheet, COLS("B:C"), 10, NULL);
|
||||
|
||||
/* Add the worksheet data that the charts will refer to. */
|
||||
worksheet_write_string(worksheet, 0, 0, "Reason", bold);
|
||||
worksheet_write_string(worksheet, 0, 1, "Number", bold);
|
||||
worksheet_write_string(worksheet, 0, 2, "Percentage", bold);
|
||||
|
||||
/* Reasons for lateness data. */
|
||||
worksheet_write_string(worksheet, 1, 0, "Traffic", NULL);
|
||||
worksheet_write_string(worksheet, 2, 0, "Child care", NULL);
|
||||
worksheet_write_string(worksheet, 3, 0, "Public Transport", NULL);
|
||||
worksheet_write_string(worksheet, 4, 0, "Weather", NULL);
|
||||
worksheet_write_string(worksheet, 5, 0, "Overslept", NULL);
|
||||
worksheet_write_string(worksheet, 6, 0, "Emergency", NULL);
|
||||
|
||||
/* Number of occurrences. */
|
||||
worksheet_write_number(worksheet, 1, 1, 60, NULL);
|
||||
worksheet_write_number(worksheet, 2, 1, 40, NULL);
|
||||
worksheet_write_number(worksheet, 3, 1, 20, NULL);
|
||||
worksheet_write_number(worksheet, 4, 1, 15, NULL);
|
||||
worksheet_write_number(worksheet, 5, 1, 10, NULL);
|
||||
worksheet_write_number(worksheet, 6, 1, 5, NULL);
|
||||
|
||||
/* Cumulative percentages. */
|
||||
worksheet_write_number(worksheet, 1, 2, 0.400, percent_format);
|
||||
worksheet_write_number(worksheet, 2, 2, 0.667, percent_format);
|
||||
worksheet_write_number(worksheet, 3, 2, 0.800, percent_format);
|
||||
worksheet_write_number(worksheet, 4, 2, 0.900, percent_format);
|
||||
worksheet_write_number(worksheet, 5, 2, 0.967, percent_format);
|
||||
worksheet_write_number(worksheet, 6, 2, 1.000, percent_format);
|
||||
|
||||
/* Create a new column chart. This will be the primary chart. */
|
||||
lxw_chart *column_chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
|
||||
|
||||
/* Add a series for the column chart. */
|
||||
chart_add_series(column_chart,
|
||||
"=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Add a chart title. */
|
||||
chart_title_set_name(column_chart, "Reasons for lateness");
|
||||
|
||||
/* Turn off the chart legend. */
|
||||
chart_legend_set_position(column_chart, LXW_CHART_LEGEND_NONE);
|
||||
|
||||
/* Set the title and scale of the Y axes. */
|
||||
chart_axis_set_name(column_chart->y_axis, "Respondents (number)");
|
||||
chart_axis_set_min(column_chart->y_axis, 0);
|
||||
chart_axis_set_max(column_chart->y_axis, 120);
|
||||
chart_axis_set_max(column_chart->y2_axis, 1);
|
||||
|
||||
/* Create a new line chart. This will be the secondary chart. */
|
||||
lxw_chart *line_chart = workbook_add_chart(workbook, LXW_CHART_LINE);
|
||||
|
||||
/* Mark the line chart as secondary so it uses the secondary axes. */
|
||||
line_chart->is_secondary = LXW_TRUE;
|
||||
|
||||
/* Add a series for the line chart, on the secondary axis. */
|
||||
lxw_chart_series *series = chart_add_series(line_chart,
|
||||
"=Sheet1!$A$2:$A$7",
|
||||
"=Sheet1!$C$2:$C$7", 1);
|
||||
|
||||
/* Add markers to the line series. */
|
||||
chart_series_set_marker_type(series, LXW_CHART_MARKER_AUTOMATIC);
|
||||
|
||||
/* Combine the column and line charts. */
|
||||
chart_combine(column_chart, line_chart);
|
||||
|
||||
/* Insert the chart into the worksheet. */
|
||||
worksheet_insert_chart(worksheet, CELL("F2"), column_chart);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
|
|
@ -37,8 +37,8 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
|
||||
|
||||
/* Configure the chart. */
|
||||
lxw_chart_series *series1 = chart_add_series(chart, NULL, "Sheet1!$A$2:$A$5");
|
||||
lxw_chart_series *series2 = chart_add_series(chart, NULL, "Sheet1!$B$2:$B$5");
|
||||
lxw_chart_series *series1 = chart_add_series(chart, NULL, "Sheet1!$A$2:$A$5", 0);
|
||||
lxw_chart_series *series2 = chart_add_series(chart, NULL, "Sheet1!$B$2:$B$5", 0);
|
||||
|
||||
chart_series_set_name(series1, "=Sheet1!$A$1");
|
||||
chart_series_set_name(series2, "=Sheet1!$B$1");
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_PIE);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "Pie sales data");
|
||||
|
|
@ -75,7 +75,7 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_PIE);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "Pie sales data");
|
||||
|
|
@ -112,7 +112,7 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_PIE);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$4", "=Sheet1!$B$2:$B$4", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "Pie sales data");
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ int main() {
|
|||
|
||||
/* Add the data series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$1:$A$2",
|
||||
"=Sheet1!$B$1:$B$2");
|
||||
"=Sheet1!$B$1:$B$2", 0);
|
||||
|
||||
/* Create some fills for the chart points/segments. */
|
||||
lxw_chart_fill red_fill = {.color = LXW_COLOR_RED };
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@ int main() {
|
|||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_RADAR);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add a second series but leave the categories and values undefined. They
|
||||
* can be defined later using the alternative syntax shown below. */
|
||||
series = chart_add_series(chart, NULL, NULL);
|
||||
series = chart_add_series(chart, NULL, NULL, 0);
|
||||
|
||||
/* Configure the series using a syntax that is easier to define programmatically. */
|
||||
chart_series_set_categories(series, "Sheet1", 1, 0, 6, 0); /* "=Sheet1!$A$2:$A$7" */
|
||||
|
|
@ -86,13 +86,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_RADAR_WITH_MARKERS);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
@ -113,13 +113,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_RADAR_FILLED);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@ int main() {
|
|||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_SCATTER);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add a second series but leave the categories and values undefined. They
|
||||
* can be defined later using the alternative syntax shown below. */
|
||||
series = chart_add_series(chart, NULL, NULL);
|
||||
series = chart_add_series(chart, NULL, NULL, 0);
|
||||
|
||||
/* Configure the series using a syntax that is easier to define programmatically. */
|
||||
chart_series_set_categories(series, "Sheet1", 1, 0, 6, 0); /* "=Sheet1!$A$2:$A$7" */
|
||||
|
|
@ -88,13 +88,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_SCATTER_STRAIGHT_WITH_MARKERS);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
@ -118,13 +118,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_SCATTER_STRAIGHT);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
@ -148,13 +148,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_SCATTER_SMOOTH_WITH_MARKERS);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
@ -178,13 +178,13 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_SCATTER_SMOOTH);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add the second series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 2". */
|
||||
chart_series_set_name(series, "=Sheet1!$C$1");
|
||||
|
|
|
|||
84
examples/chart_secondary_axis.c
Normal file
84
examples/chart_secondary_axis.c
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* An example of creating an Excel line chart with a secondary axis using
|
||||
* the libxlsxwriter library.
|
||||
*
|
||||
* A secondary Y axis allows you to display two series with different scales
|
||||
* on the same chart. The secondary Y axis appears on the right side of the
|
||||
* chart.
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("chart_secondary_axis.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
lxw_chart_series *series;
|
||||
|
||||
/* Add a bold format for the headings. */
|
||||
lxw_format *bold = workbook_add_format(workbook);
|
||||
format_set_bold(bold);
|
||||
|
||||
/* Write the worksheet data that the chart will refer to. */
|
||||
worksheet_write_string(worksheet, CELL("A1"), "Aliens", bold);
|
||||
worksheet_write_string(worksheet, CELL("B1"), "Humans", bold);
|
||||
|
||||
/* Data for the "Aliens" series - small scale (2-7). */
|
||||
worksheet_write_number(worksheet, 1, 0, 2, NULL);
|
||||
worksheet_write_number(worksheet, 2, 0, 3, NULL);
|
||||
worksheet_write_number(worksheet, 3, 0, 4, NULL);
|
||||
worksheet_write_number(worksheet, 4, 0, 5, NULL);
|
||||
worksheet_write_number(worksheet, 5, 0, 6, NULL);
|
||||
worksheet_write_number(worksheet, 6, 0, 7, NULL);
|
||||
|
||||
/* Data for the "Humans" series - larger scale (10-50). */
|
||||
worksheet_write_number(worksheet, 1, 1, 10, NULL);
|
||||
worksheet_write_number(worksheet, 2, 1, 40, NULL);
|
||||
worksheet_write_number(worksheet, 3, 1, 50, NULL);
|
||||
worksheet_write_number(worksheet, 4, 1, 20, NULL);
|
||||
worksheet_write_number(worksheet, 5, 1, 10, NULL);
|
||||
worksheet_write_number(worksheet, 6, 1, 50, NULL);
|
||||
|
||||
/* Create a line chart. */
|
||||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE);
|
||||
|
||||
/* Add the first series to the SECONDARY Y axis (y2_axis = 1).
|
||||
*
|
||||
* When y2_axis is set to 1 (LXW_TRUE), the series will be plotted
|
||||
* against the secondary Y axis on the right side of the chart.
|
||||
* This is useful when you have data with different scales.
|
||||
*/
|
||||
series = chart_add_series(chart,
|
||||
NULL,
|
||||
"=Sheet1!$A$2:$A$7",
|
||||
1); /* y2_axis = 1: Use secondary Y axis */
|
||||
chart_series_set_name(series, "=Sheet1!$A$1");
|
||||
|
||||
/* Add the second series to the PRIMARY Y axis (y2_axis = 0). */
|
||||
series = chart_add_series(chart,
|
||||
NULL,
|
||||
"=Sheet1!$B$2:$B$7",
|
||||
0); /* y2_axis = 0: Use primary Y axis */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Configure the chart legend position. */
|
||||
chart_legend_set_position(chart, LXW_CHART_LEGEND_RIGHT);
|
||||
|
||||
/* Add a chart title and axis labels. */
|
||||
chart_title_set_name(chart, "Survey results");
|
||||
chart_axis_set_name(chart->x_axis, "Days");
|
||||
chart_axis_set_name(chart->y_axis, "Population");
|
||||
chart_axis_set_name(chart->y2_axis, "Laser wounds");
|
||||
|
||||
/* Hide the major gridlines on the primary Y axis for clarity. */
|
||||
chart_axis_major_gridlines_set_visible(chart->y_axis, LXW_FALSE);
|
||||
|
||||
/* Insert the chart into the worksheet. */
|
||||
worksheet_insert_chart(worksheet, CELL("D2"), chart);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
66
examples/chart_stock.c
Normal file
66
examples/chart_stock.c
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* An example of creating Excel Stock charts with libxlsxwriter.
|
||||
*
|
||||
* Stock charts display High-Low-Close data and are suitable for financial
|
||||
* and other data that shows variation over time.
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("chart_stock.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_STOCK);
|
||||
|
||||
/* Add a bold format for the headers. */
|
||||
lxw_format *bold = workbook_add_format(workbook);
|
||||
format_set_bold(bold);
|
||||
|
||||
/* Add a date format for the date column. */
|
||||
lxw_format *date_format = workbook_add_format(workbook);
|
||||
format_set_num_format(date_format, "dd/mm/yyyy");
|
||||
|
||||
/* Add the worksheet data that the chart will refer to. */
|
||||
/* Dates as Excel serial numbers (Jan 1-5, 2007). */
|
||||
double dates[5] = {39083, 39084, 39085, 39086, 39087};
|
||||
double high[5] = {27.2, 25.03, 19.05, 20.34, 18.5};
|
||||
double low[5] = {23.49, 19.55, 15.12, 17.84, 16.34};
|
||||
double close[5] = {25.45, 23.05, 17.32, 20.45, 17.34};
|
||||
|
||||
/* Write the column headers. */
|
||||
worksheet_write_string(worksheet, 0, 0, "Date", bold);
|
||||
worksheet_write_string(worksheet, 0, 1, "High", bold);
|
||||
worksheet_write_string(worksheet, 0, 2, "Low", bold);
|
||||
worksheet_write_string(worksheet, 0, 3, "Close", bold);
|
||||
|
||||
/* Write the data columns. */
|
||||
for (int row = 0; row < 5; row++) {
|
||||
worksheet_write_number(worksheet, row + 1, 0, dates[row], date_format);
|
||||
worksheet_write_number(worksheet, row + 1, 1, high[row], NULL);
|
||||
worksheet_write_number(worksheet, row + 1, 2, low[row], NULL);
|
||||
worksheet_write_number(worksheet, row + 1, 3, close[row], NULL);
|
||||
}
|
||||
|
||||
/* Widen the columns for visibility. */
|
||||
worksheet_set_column(worksheet, COLS("A:D"), 11, NULL);
|
||||
|
||||
/* Add a series for each of the High-Low-Close columns. Stock charts
|
||||
* should have 3 series (High-Low-Close) or 4 series (Open-High-Low-Close). */
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$6", "=Sheet1!$B$2:$B$6", 0);
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$6", "=Sheet1!$C$2:$C$6", 0);
|
||||
chart_add_series(chart, "=Sheet1!$A$2:$A$6", "=Sheet1!$D$2:$D$6", 0);
|
||||
|
||||
/* Add a chart title and axis labels. */
|
||||
chart_title_set_name(chart, "High-Low-Close");
|
||||
chart_axis_set_name(chart->x_axis, "Date");
|
||||
chart_axis_set_name(chart->y_axis, "Share price");
|
||||
|
||||
/* Insert the chart into the worksheet. */
|
||||
worksheet_insert_chart(worksheet, CELL("E9"), chart);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, chart_types[chart_num]);
|
||||
snprintf(chart_title, 32, "Style %d", style_num);
|
||||
|
||||
chart_add_series(chart, NULL, "=Data!$A$1:$A$6");
|
||||
chart_add_series(chart, NULL, "=Data!$A$1:$A$6", 0);
|
||||
chart_title_set_name(chart, chart_title);
|
||||
chart_set_style(chart, style_num);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ int main() {
|
|||
chart = workbook_add_chart(workbook, LXW_CHART_LINE);
|
||||
|
||||
/* Configure the chart. */
|
||||
series = chart_add_series(chart, NULL, "Sheet1!$A$1:$A$6");
|
||||
series = chart_add_series(chart, NULL, "Sheet1!$A$1:$A$6", 0);
|
||||
|
||||
(void)series; /* Do something with series in the real examples. */
|
||||
|
||||
|
|
|
|||
|
|
@ -53,14 +53,14 @@ int main() {
|
|||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_BAR);
|
||||
|
||||
/* Add the first series to the chart. */
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7");
|
||||
series = chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$B$2:$B$7", 0);
|
||||
|
||||
/* Set the name for the series instead of the default "Series 1". */
|
||||
chart_series_set_name(series, "=Sheet1!$B$1");
|
||||
|
||||
/* Add a second series but leave the categories and values undefined. They
|
||||
* can be defined later using the alternative syntax shown below. */
|
||||
series = chart_add_series(chart, NULL, NULL);
|
||||
series = chart_add_series(chart, NULL, NULL, 0);
|
||||
|
||||
/* Configure the series using a syntax that is easier to define programmatically. */
|
||||
chart_series_set_categories(series, "Sheet1", 1, 0, 6, 0); /* "=Sheet1!$A$2:$A$7" */
|
||||
|
|
|
|||
32
examples/checkbox.c
Normal file
32
examples/checkbox.c
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* An example of inserting checkboxes into a worksheet using the
|
||||
* libxlsxwriter library.
|
||||
*
|
||||
* Checkboxes in Excel are a feature of Excel 365 versions from 2024 onwards.
|
||||
* They are boolean values displayed as checkboxes in the cells.
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("checkbox.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Widen the column for clarity. */
|
||||
worksheet_set_column(worksheet, 0, 0, 15, NULL);
|
||||
|
||||
/* Write some checkboxes with different states. */
|
||||
worksheet_insert_checkbox(worksheet, 0, 0, LXW_FALSE);
|
||||
worksheet_insert_checkbox(worksheet, 1, 0, LXW_TRUE);
|
||||
worksheet_insert_checkbox(worksheet, 2, 0, LXW_FALSE);
|
||||
worksheet_insert_checkbox(worksheet, 3, 0, LXW_TRUE);
|
||||
worksheet_insert_checkbox(worksheet, 4, 0, LXW_TRUE);
|
||||
|
||||
workbook_close(workbook);
|
||||
|
||||
return 0;
|
||||
}
|
||||
77
examples/colors.c
Normal file
77
examples/colors.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* A demonstration of the available colors and how to use them in
|
||||
* libxlsxwriter.
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("colors.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Set the column width for clarity. */
|
||||
worksheet_set_column(worksheet, 0, 0, 16, NULL);
|
||||
worksheet_set_column(worksheet, 1, 1, 10, NULL);
|
||||
|
||||
/* Define some named colors with their RGB values. */
|
||||
struct {
|
||||
const char *name;
|
||||
lxw_color_t color;
|
||||
} named_colors[] = {
|
||||
{"Black", LXW_COLOR_BLACK},
|
||||
{"Blue", LXW_COLOR_BLUE},
|
||||
{"Brown", LXW_COLOR_BROWN},
|
||||
{"Cyan", LXW_COLOR_CYAN},
|
||||
{"Gray", LXW_COLOR_GRAY},
|
||||
{"Green", LXW_COLOR_GREEN},
|
||||
{"Lime", LXW_COLOR_LIME},
|
||||
{"Magenta", LXW_COLOR_MAGENTA},
|
||||
{"Navy", LXW_COLOR_NAVY},
|
||||
{"Orange", LXW_COLOR_ORANGE},
|
||||
{"Pink", LXW_COLOR_PINK},
|
||||
{"Purple", LXW_COLOR_PURPLE},
|
||||
{"Red", LXW_COLOR_RED},
|
||||
{"Silver", LXW_COLOR_SILVER},
|
||||
{"White", LXW_COLOR_WHITE},
|
||||
{"Yellow", LXW_COLOR_YELLOW},
|
||||
};
|
||||
|
||||
int num_colors = sizeof(named_colors) / sizeof(named_colors[0]);
|
||||
|
||||
/* Write the named colors. */
|
||||
for (int row = 0; row < num_colors; row++) {
|
||||
lxw_format *color_format = workbook_add_format(workbook);
|
||||
format_set_bg_color(color_format, named_colors[row].color);
|
||||
|
||||
worksheet_write_string(worksheet, row, 0, named_colors[row].name, NULL);
|
||||
worksheet_write_blank(worksheet, row, 1, color_format);
|
||||
}
|
||||
|
||||
/* Write some user-defined RGB colors. */
|
||||
struct {
|
||||
const char *name;
|
||||
lxw_color_t color;
|
||||
} user_colors[] = {
|
||||
{"#FF7F50", 0xFF7F50}, /* Coral */
|
||||
{"#DCDCDC", 0xDCDCDC}, /* Gainsboro */
|
||||
{"#6495ED", 0x6495ED}, /* CornflowerBlue */
|
||||
{"#DAA520", 0xDAA520}, /* GoldenRod */
|
||||
};
|
||||
|
||||
int num_user_colors = sizeof(user_colors) / sizeof(user_colors[0]);
|
||||
|
||||
for (int i = 0; i < num_user_colors; i++) {
|
||||
int row = num_colors + i;
|
||||
lxw_format *color_format = workbook_add_format(workbook);
|
||||
format_set_bg_color(color_format, user_colors[i].color);
|
||||
|
||||
worksheet_write_string(worksheet, row, 0, user_colors[i].name, NULL);
|
||||
worksheet_write_blank(worksheet, row, 1, color_format);
|
||||
}
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
57
examples/right_to_left.c
Normal file
57
examples/right_to_left.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Example of how to use libxlsxwriter to change the default worksheet and
|
||||
* cell text direction from left-to-right to right-to-left as required by
|
||||
* some middle eastern versions of Excel.
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("right_to_left.xlsx");
|
||||
lxw_worksheet *worksheet1 = workbook_add_worksheet(workbook, NULL);
|
||||
lxw_worksheet *worksheet2 = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Create formats for text direction. */
|
||||
lxw_format *format_left_to_right = workbook_add_format(workbook);
|
||||
lxw_format *format_right_to_left = workbook_add_format(workbook);
|
||||
|
||||
/* Set reading order: 1 = left-to-right, 2 = right-to-left. */
|
||||
format_set_reading_order(format_left_to_right, 1);
|
||||
format_set_reading_order(format_right_to_left, 2);
|
||||
|
||||
/* Make the columns wider for clarity. */
|
||||
worksheet_set_column(worksheet1, 0, 0, 25, NULL);
|
||||
worksheet_set_column(worksheet2, 0, 0, 25, NULL);
|
||||
|
||||
/* Change the direction for worksheet2. */
|
||||
worksheet_right_to_left(worksheet2);
|
||||
|
||||
/* Write some data to show the difference. */
|
||||
/* Standard direction: | A1 | B1 | C1 | ... */
|
||||
worksheet_write_string(worksheet1, 0, 0,
|
||||
"\xd9\x86\xd8\xb5 \xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a / English text",
|
||||
NULL); /* Arabic text / English text - Default direction */
|
||||
worksheet_write_string(worksheet1, 1, 0,
|
||||
"\xd9\x86\xd8\xb5 \xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a / English text",
|
||||
format_left_to_right);
|
||||
worksheet_write_string(worksheet1, 2, 0,
|
||||
"\xd9\x86\xd8\xb5 \xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a / English text",
|
||||
format_right_to_left);
|
||||
|
||||
/* Right to left direction: ... | C1 | B1 | A1 | */
|
||||
worksheet_write_string(worksheet2, 0, 0,
|
||||
"\xd9\x86\xd8\xb5 \xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a / English text",
|
||||
NULL); /* Default direction */
|
||||
worksheet_write_string(worksheet2, 1, 0,
|
||||
"\xd9\x86\xd8\xb5 \xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a / English text",
|
||||
format_left_to_right);
|
||||
worksheet_write_string(worksheet2, 2, 0,
|
||||
"\xd9\x86\xd8\xb5 \xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a / English text",
|
||||
format_right_to_left);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
86
examples/sparklines.c
Normal file
86
examples/sparklines.c
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* An example of creating Excel sparklines with libxlsxwriter.
|
||||
*
|
||||
* Sparklines are small charts that fit in a single cell and allow you to
|
||||
* show trends in data at a glance.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org.
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("sparklines.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Set the column widths for the data and sparklines. */
|
||||
worksheet_set_column(worksheet, COLS("A:F"), 12, NULL);
|
||||
worksheet_set_column(worksheet, COLS("G:G"), 16, NULL);
|
||||
|
||||
/* Add some row headers. */
|
||||
worksheet_write_string(worksheet, 0, 0, "Line", NULL);
|
||||
worksheet_write_string(worksheet, 1, 0, "Column", NULL);
|
||||
worksheet_write_string(worksheet, 2, 0, "Win/Loss", NULL);
|
||||
worksheet_write_string(worksheet, 3, 0, "With options", NULL);
|
||||
worksheet_write_string(worksheet, 4, 0, "Custom colors", NULL);
|
||||
|
||||
/* Write the sample data. */
|
||||
int data[][5] = {
|
||||
{-2, 2, 3, -1, 0},
|
||||
{30, 20, 33, 20, 15},
|
||||
{1, -1, -1, 1, -1},
|
||||
{5, 10, 3, 8, 6},
|
||||
{2, 4, 6, 8, 10},
|
||||
};
|
||||
|
||||
for (int row = 0; row < 5; row++) {
|
||||
for (int col = 0; col < 5; col++) {
|
||||
worksheet_write_number(worksheet, row, col + 1, data[row][col], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a simple line sparkline. */
|
||||
lxw_sparkline_options line_options = {
|
||||
.range = "Sheet1!B1:F1",
|
||||
};
|
||||
worksheet_add_sparkline(worksheet, 0, 6, &line_options);
|
||||
|
||||
/* Add a column sparkline. */
|
||||
lxw_sparkline_options column_options = {
|
||||
.range = "Sheet1!B2:F2",
|
||||
.type = LXW_SPARKLINE_COLUMN,
|
||||
};
|
||||
worksheet_add_sparkline(worksheet, 1, 6, &column_options);
|
||||
|
||||
/* Add a win/loss sparkline. */
|
||||
lxw_sparkline_options winloss_options = {
|
||||
.range = "Sheet1!B3:F3",
|
||||
.type = LXW_SPARKLINE_WIN_LOSS,
|
||||
};
|
||||
worksheet_add_sparkline(worksheet, 2, 6, &winloss_options);
|
||||
|
||||
/* Add a sparkline with options: markers, high/low points, line weight. */
|
||||
lxw_sparkline_options markers_options = {
|
||||
.range = "Sheet1!B4:F4",
|
||||
.markers = LXW_TRUE,
|
||||
.high_point = LXW_TRUE,
|
||||
.low_point = LXW_TRUE,
|
||||
.first_point = LXW_TRUE,
|
||||
.last_point = LXW_TRUE,
|
||||
.weight = 1.5,
|
||||
};
|
||||
worksheet_add_sparkline(worksheet, 3, 6, &markers_options);
|
||||
|
||||
/* Add a sparkline with custom colors. */
|
||||
lxw_sparkline_options color_options = {
|
||||
.range = "Sheet1!B5:F5",
|
||||
.series_color = 0x0000FF, /* Blue line */
|
||||
.markers = LXW_TRUE,
|
||||
.markers_color = 0xFF0000, /* Red markers */
|
||||
};
|
||||
worksheet_add_sparkline(worksheet, 4, 6, &color_options);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
32
examples/text_indent.c
Normal file
32
examples/text_indent.c
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* A simple formatting example using libxlsxwriter.
|
||||
*
|
||||
* This program demonstrates the indentation cell format.
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("text_indent.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Create formats with different indentation levels. */
|
||||
lxw_format *indent1 = workbook_add_format(workbook);
|
||||
lxw_format *indent2 = workbook_add_format(workbook);
|
||||
|
||||
format_set_indent(indent1, 1);
|
||||
format_set_indent(indent2, 2);
|
||||
|
||||
/* Make the column wider for clarity. */
|
||||
worksheet_set_column(worksheet, 0, 0, 40, NULL);
|
||||
|
||||
/* Write some indented text. */
|
||||
worksheet_write_string(worksheet, 0, 0, "This text is indented 1 level", indent1);
|
||||
worksheet_write_string(worksheet, 1, 0, "This text is indented 2 levels", indent2);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
30
examples/textbox.c
Normal file
30
examples/textbox.c
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* An example of inserting textboxes into a worksheet using the
|
||||
* libxlsxwriter library.
|
||||
*
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("textbox.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Insert a simple textbox with default size. */
|
||||
worksheet_insert_textbox(worksheet, 1, 1, "This is a textbox");
|
||||
|
||||
/* Insert a textbox with custom size. */
|
||||
lxw_textbox_options options = {.width = 256, .height = 100};
|
||||
worksheet_insert_textbox_opt(worksheet, 8, 1, "A larger textbox", &options);
|
||||
|
||||
/* Insert a textbox with offset. */
|
||||
lxw_textbox_options options2 = {.x_offset = 10, .y_offset = 10};
|
||||
worksheet_insert_textbox_opt(worksheet, 15, 1, "Offset textbox", &options2);
|
||||
|
||||
workbook_close(workbook);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -19,8 +19,8 @@
|
|||
#include "xlsxwriter/format.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
|
||||
#define LXW_VERSION "1.2.3"
|
||||
#define LXW_VERSION_ID 123
|
||||
#define LXW_SOVERSION "10"
|
||||
#define LXW_VERSION "1.2.4"
|
||||
#define LXW_VERSION_ID 124
|
||||
#define LXW_SOVERSION "11"
|
||||
|
||||
#endif /* __LXW_XLSXWRITER_H__ */
|
||||
|
|
|
|||
|
|
@ -156,7 +156,10 @@ typedef enum lxw_chart_type {
|
|||
LXW_CHART_RADAR_WITH_MARKERS,
|
||||
|
||||
/** Radar chart - filled. */
|
||||
LXW_CHART_RADAR_FILLED
|
||||
LXW_CHART_RADAR_FILLED,
|
||||
|
||||
/** Stock chart. */
|
||||
LXW_CHART_STOCK
|
||||
} lxw_chart_type;
|
||||
|
||||
/**
|
||||
|
|
@ -266,7 +269,10 @@ typedef enum lxw_chart_marker_type {
|
|||
LXW_CHART_MARKER_CIRCLE,
|
||||
|
||||
/** Plus (+) marker type. */
|
||||
LXW_CHART_MARKER_PLUS
|
||||
LXW_CHART_MARKER_PLUS,
|
||||
|
||||
/** Dot marker type. */
|
||||
LXW_CHART_MARKER_DOT
|
||||
} lxw_chart_marker_type;
|
||||
|
||||
/**
|
||||
|
|
@ -485,7 +491,13 @@ typedef enum lxw_chart_axis_type {
|
|||
LXW_CHART_AXIS_TYPE_X,
|
||||
|
||||
/** Chart Y axis. */
|
||||
LXW_CHART_AXIS_TYPE_Y
|
||||
LXW_CHART_AXIS_TYPE_Y,
|
||||
|
||||
/** Chart secondary X axis. */
|
||||
LXW_CHART_AXIS_TYPE_X2,
|
||||
|
||||
/** Chart secondary Y axis. */
|
||||
LXW_CHART_AXIS_TYPE_Y2
|
||||
} lxw_chart_axis_type;
|
||||
|
||||
enum lxw_chart_subtype {
|
||||
|
|
@ -607,6 +619,21 @@ typedef enum lxw_chart_axis_tick_mark {
|
|||
LXW_CHART_AXIS_TICK_MARK_CROSSING
|
||||
} lxw_chart_tick_mark;
|
||||
|
||||
/**
|
||||
* @brief Time units for date axis major/minor units.
|
||||
*/
|
||||
typedef enum lxw_chart_axis_time_unit {
|
||||
|
||||
/** Time unit: Days. The default. */
|
||||
LXW_CHART_AXIS_TIME_UNIT_DAYS,
|
||||
|
||||
/** Time unit: Months. */
|
||||
LXW_CHART_AXIS_TIME_UNIT_MONTHS,
|
||||
|
||||
/** Time unit: Years. */
|
||||
LXW_CHART_AXIS_TIME_UNIT_YEARS
|
||||
} lxw_chart_axis_time_unit;
|
||||
|
||||
typedef struct lxw_series_range {
|
||||
char *formula;
|
||||
char *sheetname;
|
||||
|
|
@ -692,6 +719,52 @@ typedef struct lxw_chart_pattern {
|
|||
|
||||
} lxw_chart_pattern;
|
||||
|
||||
/**
|
||||
* @brief Gradient fill types for chart elements.
|
||||
*/
|
||||
typedef enum lxw_chart_gradient_fill_type {
|
||||
|
||||
/** Linear gradient fill. */
|
||||
LXW_CHART_GRADIENT_FILL_LINEAR,
|
||||
|
||||
/** Radial gradient fill. */
|
||||
LXW_CHART_GRADIENT_FILL_RADIAL,
|
||||
|
||||
/** Rectangular gradient fill. */
|
||||
LXW_CHART_GRADIENT_FILL_RECTANGULAR,
|
||||
|
||||
/** Path gradient fill. */
|
||||
LXW_CHART_GRADIENT_FILL_PATH
|
||||
|
||||
} lxw_chart_gradient_fill_type;
|
||||
|
||||
/** Maximum number of gradient stops. */
|
||||
#define LXW_CHART_GRADIENT_MAX_STOPS 10
|
||||
|
||||
/**
|
||||
* @brief Struct to represent a chart gradient fill.
|
||||
*
|
||||
* See @ref chart_gradient_fills.
|
||||
*/
|
||||
typedef struct lxw_chart_gradient_fill {
|
||||
|
||||
/** The gradient fill type. See #lxw_chart_gradient_fill_type. */
|
||||
uint8_t type;
|
||||
|
||||
/** Array of gradient colors. See @ref working_with_colors. */
|
||||
lxw_color_t colors[LXW_CHART_GRADIENT_MAX_STOPS];
|
||||
|
||||
/** Array of gradient stop positions (0-100). */
|
||||
uint8_t positions[LXW_CHART_GRADIENT_MAX_STOPS];
|
||||
|
||||
/** Number of gradient stops (2-10). */
|
||||
uint8_t num_stops;
|
||||
|
||||
/** Angle for linear gradients (0-359). Default is 90. */
|
||||
uint16_t angle;
|
||||
|
||||
} lxw_chart_gradient_fill;
|
||||
|
||||
/**
|
||||
* @brief Struct to represent a chart font.
|
||||
*
|
||||
|
|
@ -1040,6 +1113,7 @@ typedef struct lxw_chart_series {
|
|||
lxw_chart_line *line;
|
||||
lxw_chart_fill *fill;
|
||||
lxw_chart_pattern *pattern;
|
||||
lxw_chart_gradient_fill *gradient;
|
||||
lxw_chart_marker *marker;
|
||||
lxw_chart_point *points;
|
||||
lxw_chart_custom_label *data_labels;
|
||||
|
|
@ -1065,6 +1139,7 @@ typedef struct lxw_chart_series {
|
|||
lxw_chart_line *label_line;
|
||||
lxw_chart_fill *label_fill;
|
||||
lxw_chart_pattern *label_pattern;
|
||||
lxw_chart_gradient_fill *label_gradient;
|
||||
|
||||
lxw_series_error_bars *x_error_bars;
|
||||
lxw_series_error_bars *y_error_bars;
|
||||
|
|
@ -1083,6 +1158,10 @@ typedef struct lxw_chart_series {
|
|||
lxw_chart_line *trendline_line;
|
||||
double trendline_intercept;
|
||||
|
||||
/* Secondary axis flags. */
|
||||
uint8_t x2_axis;
|
||||
uint8_t y2_axis;
|
||||
|
||||
STAILQ_ENTRY (lxw_chart_series) list_pointers;
|
||||
|
||||
} lxw_chart_series;
|
||||
|
|
@ -1140,6 +1219,8 @@ typedef struct lxw_chart_axis {
|
|||
double major_unit;
|
||||
uint8_t has_minor_unit;
|
||||
double minor_unit;
|
||||
uint8_t major_unit_type;
|
||||
uint8_t minor_unit_type;
|
||||
|
||||
uint16_t interval_unit;
|
||||
uint16_t interval_tick;
|
||||
|
|
@ -1170,7 +1251,7 @@ typedef struct lxw_chart {
|
|||
uint8_t subtype;
|
||||
uint16_t series_index;
|
||||
|
||||
void (*write_chart_type)(struct lxw_chart *);
|
||||
void (*write_chart_type)(struct lxw_chart *, uint8_t primary_axes);
|
||||
void (*write_plot_area)(struct lxw_chart *);
|
||||
|
||||
/**
|
||||
|
|
@ -1185,6 +1266,18 @@ typedef struct lxw_chart {
|
|||
*/
|
||||
lxw_chart_axis *y_axis;
|
||||
|
||||
/**
|
||||
* A pointer to the chart secondary x2_axis object which can be used in
|
||||
* functions that configure the secondary X axis.
|
||||
*/
|
||||
lxw_chart_axis *x2_axis;
|
||||
|
||||
/**
|
||||
* A pointer to the chart secondary y2_axis object which can be used in
|
||||
* functions that configure the secondary Y axis.
|
||||
*/
|
||||
lxw_chart_axis *y2_axis;
|
||||
|
||||
lxw_chart_title title;
|
||||
|
||||
uint32_t id;
|
||||
|
|
@ -1193,6 +1286,10 @@ typedef struct lxw_chart {
|
|||
uint32_t axis_id_3;
|
||||
uint32_t axis_id_4;
|
||||
|
||||
uint8_t has_secondary_axis;
|
||||
struct lxw_chart *combined;
|
||||
uint8_t is_secondary;
|
||||
|
||||
uint8_t in_use;
|
||||
uint8_t chart_group;
|
||||
uint8_t cat_has_num_fmt;
|
||||
|
|
@ -1200,6 +1297,7 @@ typedef struct lxw_chart {
|
|||
|
||||
uint8_t has_horiz_cat_axis;
|
||||
uint8_t has_horiz_val_axis;
|
||||
uint8_t date_category;
|
||||
|
||||
uint8_t style_id;
|
||||
uint16_t rotation;
|
||||
|
|
@ -1223,11 +1321,13 @@ typedef struct lxw_chart {
|
|||
lxw_chart_line *chartarea_line;
|
||||
lxw_chart_fill *chartarea_fill;
|
||||
lxw_chart_pattern *chartarea_pattern;
|
||||
lxw_chart_gradient_fill *chartarea_gradient;
|
||||
|
||||
lxw_chart_line *plotarea_line;
|
||||
lxw_chart_fill *plotarea_fill;
|
||||
lxw_chart_layout *plotarea_layout;
|
||||
lxw_chart_pattern *plotarea_pattern;
|
||||
lxw_chart_gradient_fill *plotarea_gradient;
|
||||
|
||||
uint8_t has_drop_lines;
|
||||
lxw_chart_line *drop_lines_line;
|
||||
|
|
@ -1278,6 +1378,8 @@ void lxw_chart_assemble_xml_file(lxw_chart *chart);
|
|||
* @param chart Pointer to a lxw_chart instance to be configured.
|
||||
* @param categories The range of categories in the data series.
|
||||
* @param values The range of values in the data series.
|
||||
* @param y2_axis (Optional) Set to 1 (LXW_TRUE) to plot the series on the
|
||||
* secondary Y axis. Defaults to 0 (primary axis) if omitted.
|
||||
*
|
||||
* @return A lxw_chart_series object pointer.
|
||||
*
|
||||
|
|
@ -1289,7 +1391,11 @@ void lxw_chart_assemble_xml_file(lxw_chart *chart);
|
|||
* used to set the categories and values of the series:
|
||||
*
|
||||
* @code
|
||||
* // Add series on primary Y axis (y2_axis parameter is optional).
|
||||
* chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
|
||||
*
|
||||
* // Add series on secondary Y axis (explicit y2_axis = 1).
|
||||
* chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$D$2:$D$7", 1);
|
||||
* @endcode
|
||||
*
|
||||
*
|
||||
|
|
@ -1309,6 +1415,10 @@ void lxw_chart_assemble_xml_file(lxw_chart *chart);
|
|||
* only mandatory option for every chart object. This parameter links the
|
||||
* chart with the worksheet data that it displays.
|
||||
*
|
||||
* - `y2_axis`: (Optional) Set to 1 to plot the series on the secondary Y
|
||||
* axis (Y2). Defaults to 0 (primary axis) if omitted. The secondary axis
|
||||
* appears on the right side of the chart and can have a different scale.
|
||||
*
|
||||
* The `categories` and `values` should be a string formula like
|
||||
* `"=Sheet1!$A$2:$A$7"` in the same way it is represented in Excel. This is
|
||||
* convenient when recreating a chart from an example in Excel but it is
|
||||
|
|
@ -1350,9 +1460,31 @@ void lxw_chart_assemble_xml_file(lxw_chart *chart);
|
|||
* @endcode
|
||||
*
|
||||
*/
|
||||
lxw_chart_series *chart_add_series(lxw_chart *chart,
|
||||
const char *categories,
|
||||
const char *values);
|
||||
lxw_chart_series *chart_add_series_impl(lxw_chart *chart,
|
||||
const char *categories,
|
||||
const char *values,
|
||||
uint8_t y2_axis);
|
||||
|
||||
/**
|
||||
* @brief Macro wrapper for chart_add_series_impl with optional y2_axis parameter.
|
||||
*
|
||||
* This macro provides backward compatibility by defaulting y2_axis to 0
|
||||
* (primary axis) when not specified.
|
||||
*
|
||||
* Usage:
|
||||
* @code
|
||||
* // 3 arguments (y2_axis defaults to 0):
|
||||
* chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
*
|
||||
* // 4 arguments (explicit y2_axis):
|
||||
* chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 1);
|
||||
* @endcode
|
||||
*/
|
||||
#define chart_add_series(...) \
|
||||
_LXW_CHART_ADD_SERIES(__VA_ARGS__, 0)
|
||||
|
||||
#define _LXW_CHART_ADD_SERIES(chart, categories, values, y2_axis, ...) \
|
||||
chart_add_series_impl((chart), (categories), (values), (y2_axis))
|
||||
|
||||
/**
|
||||
* @brief Set a series "categories" range using row and column values.
|
||||
|
|
@ -1555,6 +1687,30 @@ void chart_series_set_invert_if_negative(lxw_chart_series *series);
|
|||
void chart_series_set_pattern(lxw_chart_series *series,
|
||||
lxw_chart_pattern *pattern);
|
||||
|
||||
/**
|
||||
* @brief Set the gradient fill properties for a chart series.
|
||||
*
|
||||
* @param series A series object created via `chart_add_series()`.
|
||||
* @param gradient A #lxw_chart_gradient_fill struct.
|
||||
*
|
||||
* Set the gradient fill properties of a chart series:
|
||||
*
|
||||
* @code
|
||||
* lxw_chart_gradient_fill gradient = {
|
||||
* .type = LXW_CHART_GRADIENT_FILL_LINEAR,
|
||||
* .colors = {0x963735, 0xF1DCDB},
|
||||
* .num_stops = 2,
|
||||
* .angle = 90
|
||||
* };
|
||||
*
|
||||
* chart_series_set_gradient(series, &gradient);
|
||||
* @endcode
|
||||
*
|
||||
* For more information see #lxw_chart_gradient_fill_type and @ref chart_gradient_fills.
|
||||
*/
|
||||
void chart_series_set_gradient(lxw_chart_series *series,
|
||||
lxw_chart_gradient_fill *gradient);
|
||||
|
||||
/**
|
||||
* @brief Set the data marker type for a series.
|
||||
*
|
||||
|
|
@ -2493,18 +2649,52 @@ void chart_series_set_error_bars_endcap(lxw_series_error_bars *error_bars,
|
|||
void chart_series_set_error_bars_line(lxw_series_error_bars *error_bars,
|
||||
lxw_chart_line *line);
|
||||
|
||||
/**
|
||||
* @brief Combine two charts into a single combined chart.
|
||||
*
|
||||
* @param chart Pointer to the primary lxw_chart instance.
|
||||
* @param combined_chart Pointer to the secondary lxw_chart to combine.
|
||||
*
|
||||
* The `%chart_combine()` function is used to combine two charts into a
|
||||
* single chart, often with a shared category axis but different value axes.
|
||||
* This is useful for showing two different data series with different
|
||||
* scales on the same chart.
|
||||
*
|
||||
* @code
|
||||
* // Create primary and secondary charts.
|
||||
* lxw_chart *column_chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
|
||||
* lxw_chart *line_chart = workbook_add_chart(workbook, LXW_CHART_LINE);
|
||||
*
|
||||
* // Add data series to each chart.
|
||||
* chart_add_series(column_chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
* chart_add_series(line_chart, NULL, "=Sheet1!$B$1:$B$5", 1); // Secondary axis
|
||||
*
|
||||
* // Combine the charts.
|
||||
* chart_combine(column_chart, line_chart);
|
||||
*
|
||||
* // Insert the combined chart into the worksheet.
|
||||
* worksheet_insert_chart(worksheet, CELL("E2"), column_chart);
|
||||
* @endcode
|
||||
*
|
||||
* Note: Only the primary chart should be inserted into the worksheet.
|
||||
* The secondary chart is managed internally.
|
||||
*/
|
||||
void chart_combine(lxw_chart *chart, lxw_chart *combined_chart);
|
||||
|
||||
/**
|
||||
* @brief Get an axis pointer from a chart.
|
||||
*
|
||||
* @param chart Pointer to a lxw_chart instance to be configured.
|
||||
* @param axis_type The axis type (X or Y): #lxw_chart_axis_type.
|
||||
* @param axis_type The axis type (X, Y, X2 or Y2): #lxw_chart_axis_type.
|
||||
*
|
||||
* The `%chart_axis_get()` function returns a pointer to a chart axis based
|
||||
* on the #lxw_chart_axis_type:
|
||||
*
|
||||
* @code
|
||||
* lxw_chart_axis *x_axis = chart_axis_get(chart, LXW_CHART_AXIS_TYPE_X);
|
||||
* lxw_chart_axis *y_axis = chart_axis_get(chart, LXW_CHART_AXIS_TYPE_Y);
|
||||
* lxw_chart_axis *x_axis = chart_axis_get(chart, LXW_CHART_AXIS_TYPE_X);
|
||||
* lxw_chart_axis *y_axis = chart_axis_get(chart, LXW_CHART_AXIS_TYPE_Y);
|
||||
* lxw_chart_axis *x2_axis = chart_axis_get(chart, LXW_CHART_AXIS_TYPE_X2);
|
||||
* lxw_chart_axis *y2_axis = chart_axis_get(chart, LXW_CHART_AXIS_TYPE_Y2);
|
||||
*
|
||||
* // Use the axis pointer in other functions.
|
||||
* chart_axis_major_gridlines_set_visible(x_axis, LXW_TRUE);
|
||||
|
|
@ -3121,6 +3311,74 @@ void chart_axis_set_major_unit(lxw_chart_axis *axis, double unit);
|
|||
*/
|
||||
void chart_axis_set_minor_unit(lxw_chart_axis *axis, double unit);
|
||||
|
||||
/**
|
||||
* @brief Set the category axis as a date axis.
|
||||
*
|
||||
* @param axis A pointer to a chart #lxw_chart_axis object.
|
||||
*
|
||||
* Set the category axis type as a date axis. A date axis is similar to a
|
||||
* category axis but it displays dates in chronological order rather than
|
||||
* just as equal categories.
|
||||
*
|
||||
* @code
|
||||
* chart_axis_set_date_axis(chart->x_axis);
|
||||
* @endcode
|
||||
*
|
||||
* This is often used with min/max, major/minor unit settings:
|
||||
*
|
||||
* @code
|
||||
* chart_axis_set_date_axis(chart->x_axis);
|
||||
* chart_axis_set_min(chart->x_axis, 41275); // Date serial number
|
||||
* chart_axis_set_max(chart->x_axis, 41282); // Date serial number
|
||||
* chart_axis_set_major_unit(chart->x_axis, 1);
|
||||
* chart_axis_set_major_unit_type(chart->x_axis, LXW_CHART_AXIS_TIME_UNIT_DAYS);
|
||||
* @endcode
|
||||
*
|
||||
* **Axis types**: This function is applicable to category axes only.
|
||||
* See @ref ww_charts_axes.
|
||||
*/
|
||||
void chart_axis_set_date_axis(lxw_chart_axis *axis);
|
||||
|
||||
/**
|
||||
* @brief Set the time unit type for the major unit of a date axis.
|
||||
*
|
||||
* @param axis A pointer to a chart #lxw_chart_axis object.
|
||||
* @param type The time unit type: #lxw_chart_axis_time_unit.
|
||||
*
|
||||
* Set the time unit type for the major units of a date axis. The default is
|
||||
* LXW_CHART_AXIS_TIME_UNIT_DAYS.
|
||||
*
|
||||
* @code
|
||||
* chart_axis_set_date_axis(chart->x_axis);
|
||||
* chart_axis_set_major_unit(chart->x_axis, 1);
|
||||
* chart_axis_set_major_unit_type(chart->x_axis, LXW_CHART_AXIS_TIME_UNIT_MONTHS);
|
||||
* @endcode
|
||||
*
|
||||
* **Axis types**: This function is applicable to date axes only.
|
||||
* See @ref ww_charts_axes.
|
||||
*/
|
||||
void chart_axis_set_major_unit_type(lxw_chart_axis *axis, uint8_t type);
|
||||
|
||||
/**
|
||||
* @brief Set the time unit type for the minor unit of a date axis.
|
||||
*
|
||||
* @param axis A pointer to a chart #lxw_chart_axis object.
|
||||
* @param type The time unit type: #lxw_chart_axis_time_unit.
|
||||
*
|
||||
* Set the time unit type for the minor units of a date axis. The default is
|
||||
* LXW_CHART_AXIS_TIME_UNIT_DAYS.
|
||||
*
|
||||
* @code
|
||||
* chart_axis_set_date_axis(chart->x_axis);
|
||||
* chart_axis_set_minor_unit(chart->x_axis, 1);
|
||||
* chart_axis_set_minor_unit_type(chart->x_axis, LXW_CHART_AXIS_TIME_UNIT_DAYS);
|
||||
* @endcode
|
||||
*
|
||||
* **Axis types**: This function is applicable to date axes only.
|
||||
* See @ref ww_charts_axes.
|
||||
*/
|
||||
void chart_axis_set_minor_unit_type(lxw_chart_axis *axis, uint8_t type);
|
||||
|
||||
/**
|
||||
* @brief Set the display units for a value axis.
|
||||
*
|
||||
|
|
@ -3545,6 +3803,19 @@ void chart_chartarea_set_fill(lxw_chart *chart, lxw_chart_fill *fill);
|
|||
void chart_chartarea_set_pattern(lxw_chart *chart,
|
||||
lxw_chart_pattern *pattern);
|
||||
|
||||
/**
|
||||
* @brief Set the gradient fill properties for a chart area.
|
||||
*
|
||||
* @param chart Pointer to a lxw_chart instance to be configured.
|
||||
* @param gradient A #lxw_chart_gradient_fill struct.
|
||||
*
|
||||
* Set the gradient fill properties of a chart area.
|
||||
*
|
||||
* For more information see #lxw_chart_gradient_fill_type.
|
||||
*/
|
||||
void chart_chartarea_set_gradient(lxw_chart *chart,
|
||||
lxw_chart_gradient_fill *gradient);
|
||||
|
||||
/**
|
||||
* @brief Set the line properties for a plotarea.
|
||||
*
|
||||
|
|
@ -3605,6 +3876,19 @@ void chart_plotarea_set_fill(lxw_chart *chart, lxw_chart_fill *fill);
|
|||
*/
|
||||
void chart_plotarea_set_pattern(lxw_chart *chart, lxw_chart_pattern *pattern);
|
||||
|
||||
/**
|
||||
* @brief Set the gradient fill properties for a chart plotarea.
|
||||
*
|
||||
* @param chart Pointer to a lxw_chart instance to be configured.
|
||||
* @param gradient A #lxw_chart_gradient_fill struct.
|
||||
*
|
||||
* Set the gradient fill properties of a chart plotarea.
|
||||
*
|
||||
* For more information see #lxw_chart_gradient_fill_type.
|
||||
*/
|
||||
void chart_plotarea_set_gradient(lxw_chart *chart,
|
||||
lxw_chart_gradient_fill *gradient);
|
||||
|
||||
/**
|
||||
* @brief Set the manual layout of the chart plotarea.
|
||||
*
|
||||
|
|
@ -3867,6 +4151,50 @@ void chart_set_series_overlap(lxw_chart *chart, int8_t overlap);
|
|||
*/
|
||||
void chart_set_series_gap(lxw_chart *chart, uint16_t gap);
|
||||
|
||||
/**
|
||||
* @brief Set the overlap between series in a Bar/Column chart for the
|
||||
* secondary axis.
|
||||
*
|
||||
* @param chart Pointer to a lxw_chart instance to be configured.
|
||||
* @param overlap The overlap between the series. -100 to 100.
|
||||
*
|
||||
* The `%chart_set_series_overlap_y2()` function sets the overlap between
|
||||
* series in Bar and Column charts for the secondary axis. It is identical
|
||||
* to `chart_set_series_overlap()` but applies to the secondary Y axis.
|
||||
*
|
||||
* @code
|
||||
* chart_set_series_overlap_y2(chart, -27);
|
||||
* @endcode
|
||||
*
|
||||
* The overlap value must be in the range `-100 <= overlap <= 100`.
|
||||
* The default value is 0.
|
||||
*
|
||||
* This option is only available for Bar/Column charts with a secondary axis.
|
||||
*/
|
||||
void chart_set_series_overlap_y2(lxw_chart *chart, int8_t overlap);
|
||||
|
||||
/**
|
||||
* @brief Set the gap between series in a Bar/Column chart for the
|
||||
* secondary axis.
|
||||
*
|
||||
* @param chart Pointer to a lxw_chart instance to be configured.
|
||||
* @param gap The gap between the series. 0 to 500.
|
||||
*
|
||||
* The `%chart_set_series_gap_y2()` function sets the gap between series in
|
||||
* Bar and Column charts for the secondary axis. It is identical to
|
||||
* `chart_set_series_gap()` but applies to the secondary Y axis.
|
||||
*
|
||||
* @code
|
||||
* chart_set_series_gap_y2(chart, 251);
|
||||
* @endcode
|
||||
*
|
||||
* The gap value must be in the range `0 <= gap <= 500`. The default value
|
||||
* is 150.
|
||||
*
|
||||
* This option is only available for Bar/Column charts with a secondary axis.
|
||||
*/
|
||||
void chart_set_series_gap_y2(lxw_chart *chart, uint16_t gap);
|
||||
|
||||
/**
|
||||
* @brief Set the option for displaying blank data in a chart.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ void lxw_ct_add_calc_chain(lxw_content_types *content_types);
|
|||
void lxw_ct_add_custom_properties(lxw_content_types *content_types);
|
||||
void lxw_ct_add_metadata(lxw_content_types *content_types);
|
||||
void lxw_ct_add_rich_value(lxw_content_types *content_types);
|
||||
void lxw_ct_add_feature_property_bag(lxw_content_types *content_types);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
|
|
|||
|
|
@ -32,6 +32,42 @@ enum image_types {
|
|||
LXW_IMAGE_GIF
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Options for inserted textboxes.
|
||||
*
|
||||
*/
|
||||
typedef struct lxw_textbox_options {
|
||||
|
||||
/** Width of the textbox in pixels. Default is 192. */
|
||||
uint32_t width;
|
||||
|
||||
/** Height of the textbox in pixels. Default is 120. */
|
||||
uint32_t height;
|
||||
|
||||
/** X offset from the cell in pixels. Default is 0. */
|
||||
int32_t x_offset;
|
||||
|
||||
/** Y offset from the cell in pixels. Default is 0. */
|
||||
int32_t y_offset;
|
||||
|
||||
/** X scale of the textbox. Default is 1.0. */
|
||||
double x_scale;
|
||||
|
||||
/** Y scale of the textbox. Default is 1.0. */
|
||||
double y_scale;
|
||||
|
||||
/** Object position/anchor: #lxw_object_position. Default is
|
||||
LXW_OBJECT_MOVE_AND_SIZE. */
|
||||
uint8_t object_position;
|
||||
|
||||
/** Alt text description of the textbox. */
|
||||
const char *description;
|
||||
|
||||
/** Mark textbox as decorative. */
|
||||
uint8_t decorative;
|
||||
|
||||
} lxw_textbox_options;
|
||||
|
||||
/* Coordinates used in a drawing object. */
|
||||
typedef struct lxw_drawing_coords {
|
||||
uint32_t col;
|
||||
|
|
@ -56,6 +92,7 @@ typedef struct lxw_drawing_object {
|
|||
char *description;
|
||||
char *tip;
|
||||
uint8_t decorative;
|
||||
char *text;
|
||||
|
||||
STAILQ_ENTRY (lxw_drawing_object) list_pointers;
|
||||
|
||||
|
|
|
|||
56
include/xlsxwriter/feature_property_bag.h
Normal file
56
include/xlsxwriter/feature_property_bag.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org.
|
||||
*
|
||||
* feature_property_bag - A libxlsxwriter library for creating Excel XLSX
|
||||
* featurePropertyBag files.
|
||||
*
|
||||
*/
|
||||
#ifndef __LXW_FEATURE_PROPERTY_BAG_H__
|
||||
#define __LXW_FEATURE_PROPERTY_BAG_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* Feature property bag types. */
|
||||
#define LXW_FEATURE_BAG_NONE 0
|
||||
#define LXW_FEATURE_BAG_XF_COMPLEMENTS 1
|
||||
#define LXW_FEATURE_BAG_DXF_COMPLEMENTS 2
|
||||
|
||||
/*
|
||||
* Struct to represent a feature_property_bag.
|
||||
*/
|
||||
typedef struct lxw_feature_property_bag {
|
||||
|
||||
FILE *file;
|
||||
uint8_t has_xf_complements;
|
||||
uint8_t has_dxf_complements;
|
||||
|
||||
} lxw_feature_property_bag;
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
lxw_feature_property_bag *lxw_feature_property_bag_new(void);
|
||||
void lxw_feature_property_bag_free(lxw_feature_property_bag *feature_property_bag);
|
||||
void lxw_feature_property_bag_assemble_xml_file(lxw_feature_property_bag *self);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
||||
#endif /* TESTING */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* __LXW_FEATURE_PROPERTY_BAG_H__ */
|
||||
|
|
@ -438,6 +438,8 @@ typedef struct lxw_format {
|
|||
|
||||
uint8_t quote_prefix;
|
||||
|
||||
uint8_t checkbox;
|
||||
|
||||
STAILQ_ENTRY (lxw_format) list_pointers;
|
||||
} lxw_format;
|
||||
|
||||
|
|
@ -1333,6 +1335,26 @@ void format_set_diag_color(lxw_format *format, lxw_color_t color);
|
|||
*/
|
||||
void format_set_quote_prefix(lxw_format *format);
|
||||
|
||||
/**
|
||||
* @brief Set the checkbox property for a cell format.
|
||||
*
|
||||
* @param format Pointer to a Format instance.
|
||||
*
|
||||
* Set the checkbox property of a format. This allows a boolean value to be
|
||||
* displayed as a checkbox in Excel. It is generally easier to create a
|
||||
* checkbox using the worksheet_insert_checkbox() function which
|
||||
* automatically sets this property.
|
||||
*
|
||||
* @code
|
||||
* lxw_format *checkbox_format = workbook_add_format(workbook);
|
||||
* format_set_checkbox(checkbox_format);
|
||||
*
|
||||
* worksheet_write_boolean(worksheet, 0, 0, 1, checkbox_format);
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
void format_set_checkbox(lxw_format *format);
|
||||
|
||||
void format_set_font_outline(lxw_format *format);
|
||||
void format_set_font_shadow(lxw_format *format);
|
||||
void format_set_font_scheme(lxw_format *format, const char *font_scheme);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "rich_value_rel.h"
|
||||
#include "rich_value_types.h"
|
||||
#include "rich_value_structure.h"
|
||||
#include "feature_property_bag.h"
|
||||
|
||||
#define LXW_ZIP_BUFFER_SIZE (16384)
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ void lxw_add_worksheet_relationship(lxw_relationships *self, const char *type,
|
|||
const char *target,
|
||||
const char *target_mode);
|
||||
void lxw_add_rich_value_relationship(lxw_relationships *self);
|
||||
void lxw_add_feature_property_bag_relationship(lxw_relationships *self);
|
||||
|
||||
/* Declarations required for unit testing. */
|
||||
#ifdef TESTING
|
||||
|
|
|
|||
205
include/xlsxwriter/sparkline.h
Normal file
205
include/xlsxwriter/sparkline.h
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file sparkline.h
|
||||
*
|
||||
* @brief Sparkline options and types for libxlsxwriter.
|
||||
*
|
||||
* Sparklines are small charts that fit in a single cell and allow you to
|
||||
* show trends in data at a glance.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LXW_SPARKLINE_H__
|
||||
#define __LXW_SPARKLINE_H__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
* @brief Sparkline types.
|
||||
*/
|
||||
typedef enum lxw_sparkline_type {
|
||||
/** Line sparkline (default). */
|
||||
LXW_SPARKLINE_LINE = 0,
|
||||
|
||||
/** Column sparkline. */
|
||||
LXW_SPARKLINE_COLUMN,
|
||||
|
||||
/** Win/Loss sparkline. */
|
||||
LXW_SPARKLINE_WIN_LOSS
|
||||
} lxw_sparkline_type;
|
||||
|
||||
/**
|
||||
* @brief Sparkline empty cell handling.
|
||||
*/
|
||||
typedef enum lxw_sparkline_empty_cells {
|
||||
/** Show empty cells as gaps (default). */
|
||||
LXW_SPARKLINE_EMPTY_CELLS_GAP = 0,
|
||||
|
||||
/** Show empty cells as zeros. */
|
||||
LXW_SPARKLINE_EMPTY_CELLS_ZERO,
|
||||
|
||||
/** Connect points across empty cells. */
|
||||
LXW_SPARKLINE_EMPTY_CELLS_SPAN
|
||||
} lxw_sparkline_empty_cells;
|
||||
|
||||
/**
|
||||
* @brief Sparkline axis type for min/max.
|
||||
*/
|
||||
typedef enum lxw_sparkline_axis_type {
|
||||
/** Axis value is automatic (default). */
|
||||
LXW_SPARKLINE_AXIS_AUTOMATIC = 0,
|
||||
|
||||
/** Axis value is same for all sparklines in group. */
|
||||
LXW_SPARKLINE_AXIS_GROUP,
|
||||
|
||||
/** Axis value is set to a custom value. */
|
||||
LXW_SPARKLINE_AXIS_CUSTOM
|
||||
} lxw_sparkline_axis_type;
|
||||
|
||||
/**
|
||||
* @brief Sparkline options.
|
||||
*
|
||||
* The members of this struct are used to define a sparkline that is inserted
|
||||
* into a worksheet via worksheet_add_sparkline().
|
||||
*/
|
||||
typedef struct lxw_sparkline_options {
|
||||
|
||||
/** A string containing the range of data for the sparkline in a format
|
||||
* like "Sheet1!$A$1:$E$1". Required. */
|
||||
const char *range;
|
||||
|
||||
/** A string containing the cell location of the sparkline. If this is
|
||||
* NULL, the location is specified by row/col parameters. */
|
||||
const char *location;
|
||||
|
||||
/** The type of sparkline: line, column, or win/loss.
|
||||
* See #lxw_sparkline_type. Default is LXW_SPARKLINE_LINE. */
|
||||
uint8_t type;
|
||||
|
||||
/** The style index (0-35) from the predefined Excel sparkline styles.
|
||||
* Default is 0. */
|
||||
uint8_t style;
|
||||
|
||||
/** Show high point marker. */
|
||||
uint8_t high_point;
|
||||
|
||||
/** Show low point marker. */
|
||||
uint8_t low_point;
|
||||
|
||||
/** Show negative point markers. */
|
||||
uint8_t negative_points;
|
||||
|
||||
/** Show first point marker. */
|
||||
uint8_t first_point;
|
||||
|
||||
/** Show last point marker. */
|
||||
uint8_t last_point;
|
||||
|
||||
/** Show markers on all points (line sparkline only). */
|
||||
uint8_t markers;
|
||||
|
||||
/** Custom color for sparkline series (RGB). Use 0 for style default. */
|
||||
lxw_color_t series_color;
|
||||
|
||||
/** Custom color for negative values (RGB). Use 0 for style default. */
|
||||
lxw_color_t negative_color;
|
||||
|
||||
/** Custom color for markers (RGB). Use 0 for style default. */
|
||||
lxw_color_t markers_color;
|
||||
|
||||
/** Custom color for first point (RGB). Use 0 for style default. */
|
||||
lxw_color_t first_color;
|
||||
|
||||
/** Custom color for last point (RGB). Use 0 for style default. */
|
||||
lxw_color_t last_color;
|
||||
|
||||
/** Custom color for high point (RGB). Use 0 for style default. */
|
||||
lxw_color_t high_color;
|
||||
|
||||
/** Custom color for low point (RGB). Use 0 for style default. */
|
||||
lxw_color_t low_color;
|
||||
|
||||
/** Minimum axis value for sparkline. */
|
||||
double min;
|
||||
|
||||
/** Maximum axis value for sparkline. */
|
||||
double max;
|
||||
|
||||
/** How min axis is calculated. See #lxw_sparkline_axis_type. */
|
||||
uint8_t min_axis_type;
|
||||
|
||||
/** How max axis is calculated. See #lxw_sparkline_axis_type. */
|
||||
uint8_t max_axis_type;
|
||||
|
||||
/** Show the horizontal axis. */
|
||||
uint8_t show_axis;
|
||||
|
||||
/** Reverse the order of the data (right to left). */
|
||||
uint8_t reverse;
|
||||
|
||||
/** Show data in hidden rows. */
|
||||
uint8_t show_hidden;
|
||||
|
||||
/** How empty cells are handled. See #lxw_sparkline_empty_cells. */
|
||||
uint8_t empty_cells;
|
||||
|
||||
/** Line weight in points (e.g., 0.75, 1.0, 2.25). Default is 0.75. */
|
||||
double weight;
|
||||
|
||||
/** Range containing date axis data. */
|
||||
const char *date_axis;
|
||||
|
||||
} lxw_sparkline_options;
|
||||
|
||||
/* Internal sparkline structure with resolved values */
|
||||
typedef struct lxw_sparkline {
|
||||
|
||||
STAILQ_ENTRY(lxw_sparkline) list_pointers;
|
||||
|
||||
char *range;
|
||||
lxw_row_t row;
|
||||
lxw_col_t col;
|
||||
char *location;
|
||||
|
||||
uint8_t type;
|
||||
uint8_t style;
|
||||
|
||||
uint8_t high_point;
|
||||
uint8_t low_point;
|
||||
uint8_t negative_points;
|
||||
uint8_t first_point;
|
||||
uint8_t last_point;
|
||||
uint8_t markers;
|
||||
|
||||
lxw_color_t series_color;
|
||||
lxw_color_t negative_color;
|
||||
lxw_color_t markers_color;
|
||||
lxw_color_t first_color;
|
||||
lxw_color_t last_color;
|
||||
lxw_color_t high_color;
|
||||
lxw_color_t low_color;
|
||||
|
||||
double min;
|
||||
double max;
|
||||
uint8_t min_axis_type;
|
||||
uint8_t max_axis_type;
|
||||
|
||||
uint8_t show_axis;
|
||||
uint8_t reverse;
|
||||
uint8_t show_hidden;
|
||||
uint8_t empty_cells;
|
||||
|
||||
double weight;
|
||||
char *date_axis;
|
||||
|
||||
} lxw_sparkline;
|
||||
|
||||
STAILQ_HEAD(lxw_sparklines, lxw_sparkline);
|
||||
|
||||
#endif /* __LXW_SPARKLINE_H__ */
|
||||
|
|
@ -300,6 +300,47 @@ int lxw_sprintf_dbl(char *data, double number);
|
|||
|
||||
uint16_t lxw_hash_password(const char *password);
|
||||
|
||||
/**
|
||||
* @brief Calculate the pixel width of a string based on character widths.
|
||||
*
|
||||
* @param string The string to calculate width for.
|
||||
*
|
||||
* @return The pixel width of the string using Calibri 11 font metrics.
|
||||
* Returns 0 if the string is NULL or empty.
|
||||
* Unhandled characters (including UTF-8) default to width 8.
|
||||
*
|
||||
* This function is useful for calculating column widths when implementing
|
||||
* autofit-like functionality. Excel stores column widths, not autofit state,
|
||||
* so applications must calculate widths themselves.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* uint16_t pixels = lxw_pixel_width("Hello World");
|
||||
* double width = lxw_autofit_width("Hello World");
|
||||
* worksheet_set_column(worksheet, 0, 0, width, NULL);
|
||||
* @endcode
|
||||
*/
|
||||
uint16_t lxw_pixel_width(const char *string);
|
||||
|
||||
/**
|
||||
* @brief Calculate the column width required to autofit a string.
|
||||
*
|
||||
* @param string The string to calculate width for.
|
||||
*
|
||||
* @return The column width in Excel character units, suitable for use with
|
||||
* worksheet_set_column(). Returns 0 if the string is NULL or empty.
|
||||
*
|
||||
* This function calculates the pixel width of the string, adds 7 pixels of
|
||||
* padding (as Excel does), and converts to column units.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* double width = lxw_autofit_width("Hello World");
|
||||
* worksheet_set_column(worksheet, 0, 0, width, NULL);
|
||||
* @endcode
|
||||
*/
|
||||
double lxw_autofit_width(const char *string);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -343,6 +343,7 @@ typedef struct lxw_workbook {
|
|||
uint8_t has_metadata;
|
||||
uint8_t has_embedded_images;
|
||||
uint8_t has_dynamic_functions;
|
||||
uint8_t has_feature_property_bags;
|
||||
uint8_t has_embedded_image_descriptions;
|
||||
|
||||
lxw_hash_table *used_xf_formats;
|
||||
|
|
@ -356,6 +357,8 @@ typedef struct lxw_workbook {
|
|||
|
||||
lxw_format *default_url_format;
|
||||
|
||||
lxw_format *checkbox_format;
|
||||
|
||||
} lxw_workbook;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include "styles.h"
|
||||
#include "utility.h"
|
||||
#include "relationships.h"
|
||||
#include "sparkline.h"
|
||||
|
||||
#define LXW_ROW_MAX 1048576
|
||||
#define LXW_COL_MAX 16384
|
||||
|
|
@ -821,6 +822,7 @@ STAILQ_HEAD(lxw_cond_format_list, lxw_cond_format_obj);
|
|||
STAILQ_HEAD(lxw_image_props, lxw_object_properties);
|
||||
STAILQ_HEAD(lxw_embedded_image_props, lxw_object_properties);
|
||||
STAILQ_HEAD(lxw_chart_props, lxw_object_properties);
|
||||
STAILQ_HEAD(lxw_textbox_props, lxw_object_properties);
|
||||
STAILQ_HEAD(lxw_comment_objs, lxw_vml_obj);
|
||||
STAILQ_HEAD(lxw_table_objs, lxw_table_obj);
|
||||
|
||||
|
|
@ -1814,6 +1816,8 @@ typedef struct lxw_object_properties {
|
|||
char *image_position;
|
||||
uint8_t decorative;
|
||||
lxw_format *format;
|
||||
char *text;
|
||||
uint8_t is_textbox;
|
||||
|
||||
STAILQ_ENTRY (lxw_object_properties) list_pointers;
|
||||
} lxw_object_properties;
|
||||
|
|
@ -2129,6 +2133,7 @@ typedef struct lxw_worksheet {
|
|||
struct lxw_image_props *image_props;
|
||||
struct lxw_image_props *embedded_image_props;
|
||||
struct lxw_chart_props *chart_data;
|
||||
struct lxw_textbox_props *textbox_data;
|
||||
struct lxw_drawing_rel_ids *drawing_rel_ids;
|
||||
struct lxw_vml_drawing_rel_ids *vml_drawing_rel_ids;
|
||||
struct lxw_comment_objs *comment_objs;
|
||||
|
|
@ -2136,6 +2141,8 @@ typedef struct lxw_worksheet {
|
|||
struct lxw_comment_objs *button_objs;
|
||||
struct lxw_table_objs *table_objs;
|
||||
uint16_t table_count;
|
||||
struct lxw_sparklines *sparklines;
|
||||
uint8_t has_sparklines;
|
||||
|
||||
lxw_row_t dim_rowmin;
|
||||
lxw_row_t dim_rowmax;
|
||||
|
|
@ -2254,6 +2261,7 @@ typedef struct lxw_worksheet {
|
|||
|
||||
lxw_drawing *drawing;
|
||||
lxw_format *default_url_format;
|
||||
lxw_format *checkbox_format;
|
||||
|
||||
uint8_t has_vml;
|
||||
uint8_t has_comments;
|
||||
|
|
@ -2287,6 +2295,9 @@ typedef struct lxw_worksheet {
|
|||
|
||||
uint8_t use_1904_epoch;
|
||||
|
||||
uint8_t has_checkboxes;
|
||||
uint8_t has_textboxes;
|
||||
|
||||
uint16_t excel_version;
|
||||
|
||||
lxw_object_properties **header_footer_objs[LXW_HEADER_FOOTER_OBJS_MAX];
|
||||
|
|
@ -2319,6 +2330,7 @@ typedef struct lxw_worksheet_init_data {
|
|||
const char *quoted_name;
|
||||
const char *tmpdir;
|
||||
lxw_format *default_url_format;
|
||||
lxw_format *checkbox_format;
|
||||
uint16_t max_url_length;
|
||||
uint8_t use_1904_epoch;
|
||||
|
||||
|
|
@ -2943,6 +2955,37 @@ lxw_error worksheet_write_boolean(lxw_worksheet *worksheet,
|
|||
lxw_row_t row, lxw_col_t col,
|
||||
int value, lxw_format *format);
|
||||
|
||||
/**
|
||||
* @brief Write a checkbox to a worksheet cell.
|
||||
*
|
||||
* @param worksheet Pointer to a lxw_worksheet instance to be updated.
|
||||
* @param row The zero indexed row number.
|
||||
* @param col The zero indexed column number.
|
||||
* @param value The checkbox state: 0 = unchecked, non-zero = checked.
|
||||
*
|
||||
* @return A #lxw_error code.
|
||||
*
|
||||
* Insert a checkbox into a worksheet cell. The `value` parameter can be
|
||||
* 0 for an unchecked checkbox or any non-zero value for a checked checkbox:
|
||||
*
|
||||
* @code
|
||||
* // Insert an unchecked checkbox in cell A1.
|
||||
* worksheet_insert_checkbox(worksheet, 0, 0, 0);
|
||||
*
|
||||
* // Insert a checked checkbox in cell A2.
|
||||
* worksheet_insert_checkbox(worksheet, 1, 0, 1);
|
||||
* @endcode
|
||||
*
|
||||
* @image html checkbox01.png
|
||||
*
|
||||
* Note: Checkbox is a feature introduced in Excel 365 and may not work
|
||||
* in older versions of Excel.
|
||||
*
|
||||
*/
|
||||
lxw_error worksheet_insert_checkbox(lxw_worksheet *worksheet,
|
||||
lxw_row_t row, lxw_col_t col,
|
||||
int value);
|
||||
|
||||
/**
|
||||
* @brief Write a formatted blank worksheet cell.
|
||||
*
|
||||
|
|
@ -4058,6 +4101,62 @@ lxw_error worksheet_insert_chart_opt(lxw_worksheet *worksheet,
|
|||
lxw_chart *chart,
|
||||
lxw_chart_options *user_options);
|
||||
|
||||
/**
|
||||
* @brief Insert a textbox object into a worksheet.
|
||||
*
|
||||
* @param worksheet Pointer to a lxw_worksheet instance to be updated.
|
||||
* @param row The zero indexed row number.
|
||||
* @param col The zero indexed column number.
|
||||
* @param text The text string to display in the textbox.
|
||||
*
|
||||
* @return A #lxw_error code.
|
||||
*
|
||||
* This function can be used to insert a textbox into a worksheet:
|
||||
*
|
||||
* @code
|
||||
* worksheet_insert_textbox(worksheet, 1, 1, "This is a textbox");
|
||||
* @endcode
|
||||
*
|
||||
* The default textbox size is 192 x 120 pixels (approximately 3 columns x 6
|
||||
* rows). The size and position of the textbox can be modified using the
|
||||
* `worksheet_insert_textbox_opt()` function and the #lxw_textbox_options
|
||||
* struct.
|
||||
*
|
||||
*/
|
||||
lxw_error worksheet_insert_textbox(lxw_worksheet *worksheet,
|
||||
lxw_row_t row, lxw_col_t col,
|
||||
const char *text);
|
||||
|
||||
/**
|
||||
* @brief Insert a textbox object into a worksheet, with options.
|
||||
*
|
||||
* @param worksheet Pointer to a lxw_worksheet instance to be updated.
|
||||
* @param row The zero indexed row number.
|
||||
* @param col The zero indexed column number.
|
||||
* @param text The text string to display in the textbox.
|
||||
* @param user_options Optional textbox parameters.
|
||||
*
|
||||
* @return A #lxw_error code.
|
||||
*
|
||||
* The `%worksheet_insert_textbox_opt()` function is like
|
||||
* `worksheet_insert_textbox()` function except that it takes an optional
|
||||
* #lxw_textbox_options struct to set the size and position of the textbox:
|
||||
*
|
||||
* @code
|
||||
* lxw_textbox_options options = {.width = 256, .height = 100};
|
||||
*
|
||||
* worksheet_insert_textbox_opt(worksheet, 1, 1, "A textbox", &options);
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* The #lxw_textbox_options struct is defined in drawing.h.
|
||||
*
|
||||
*/
|
||||
lxw_error worksheet_insert_textbox_opt(lxw_worksheet *worksheet,
|
||||
lxw_row_t row, lxw_col_t col,
|
||||
const char *text,
|
||||
lxw_textbox_options *user_options);
|
||||
|
||||
/**
|
||||
* @brief Merge a range of cells.
|
||||
*
|
||||
|
|
@ -4517,6 +4616,44 @@ lxw_error worksheet_add_table(lxw_worksheet *worksheet, lxw_row_t first_row,
|
|||
lxw_col_t first_col, lxw_row_t last_row,
|
||||
lxw_col_t last_col, lxw_table_options *options);
|
||||
|
||||
/**
|
||||
* @brief Add a sparkline to a worksheet cell.
|
||||
*
|
||||
* @param worksheet Pointer to a lxw_worksheet instance to be updated.
|
||||
* @param row The zero indexed row number.
|
||||
* @param col The zero indexed column number.
|
||||
* @param options A #lxw_sparkline_options struct to define the sparkline.
|
||||
*
|
||||
* @return A #lxw_error code.
|
||||
*
|
||||
* The `%worksheet_add_sparkline()` function is used to add a sparkline to a
|
||||
* worksheet cell. Sparklines are small charts that fit in a single cell and
|
||||
* allow you to show trends in data at a glance.
|
||||
*
|
||||
* @code
|
||||
* lxw_sparkline_options options = {
|
||||
* .range = "Sheet1!A1:E1",
|
||||
* .type = LXW_SPARKLINE_COLUMN,
|
||||
* };
|
||||
*
|
||||
* worksheet_add_sparkline(worksheet, 0, 5, &options);
|
||||
* @endcode
|
||||
*
|
||||
* The `range` parameter is required and specifies the data range that the
|
||||
* sparkline will display. It should be a string like "Sheet1!A1:E1".
|
||||
*
|
||||
* The `type` parameter specifies the sparkline type: #LXW_SPARKLINE_LINE
|
||||
* (default), #LXW_SPARKLINE_COLUMN, or #LXW_SPARKLINE_WIN_LOSS.
|
||||
*
|
||||
* The `style` parameter specifies one of 36 predefined styles (0-35).
|
||||
*
|
||||
* See @ref sparkline.h for all available options.
|
||||
*
|
||||
*/
|
||||
lxw_error worksheet_add_sparkline(lxw_worksheet *worksheet,
|
||||
lxw_row_t row, lxw_col_t col,
|
||||
lxw_sparkline_options *options);
|
||||
|
||||
/**
|
||||
* @brief Make a worksheet the active, i.e., visible worksheet.
|
||||
*
|
||||
|
|
@ -5926,6 +6063,10 @@ void lxw_worksheet_prepare_chart(lxw_worksheet *worksheet,
|
|||
lxw_object_properties *object_props,
|
||||
uint8_t is_chartsheet);
|
||||
|
||||
void lxw_worksheet_prepare_textbox(lxw_worksheet *worksheet,
|
||||
uint32_t drawing_id,
|
||||
lxw_object_properties *object_props);
|
||||
|
||||
uint32_t lxw_worksheet_prepare_vml_objects(lxw_worksheet *worksheet,
|
||||
uint32_t vml_data_id,
|
||||
uint32_t vml_shape_id,
|
||||
|
|
|
|||
1463
src/chart.c
1463
src/chart.c
File diff suppressed because it is too large
Load diff
|
|
@ -411,3 +411,14 @@ lxw_ct_add_rich_value(lxw_content_types *self)
|
|||
LXW_APP_MSEXCEL "richvaluerel+xml");
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the featurePropertyBag file to the ContentTypes overrides.
|
||||
*/
|
||||
void
|
||||
lxw_ct_add_feature_property_bag(lxw_content_types *self)
|
||||
{
|
||||
lxw_ct_add_override(self,
|
||||
"/xl/featurePropertyBag/featurePropertyBag.xml",
|
||||
LXW_APP_MSEXCEL "featurepropertybag+xml");
|
||||
}
|
||||
|
|
|
|||
326
src/drawing.c
326
src/drawing.c
|
|
@ -57,6 +57,7 @@ lxw_free_drawing_object(lxw_drawing_object *drawing_object)
|
|||
|
||||
free(drawing_object->description);
|
||||
free(drawing_object->tip);
|
||||
free(drawing_object->text);
|
||||
|
||||
free(drawing_object);
|
||||
}
|
||||
|
|
@ -603,6 +604,324 @@ _drawing_write_pic(lxw_drawing *self, uint32_t index,
|
|||
lxw_xml_end_tag(self->file, "xdr:pic");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <xdr:cNvSpPr> element for textbox shapes.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_c_nv_sp_pr_textbox(lxw_drawing *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_INT("txBox", 1);
|
||||
|
||||
lxw_xml_empty_tag(self->file, "xdr:cNvSpPr", &attributes);
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <xdr:nvSpPr> element for shapes.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_nv_sp_pr(lxw_drawing *self, uint32_t index,
|
||||
lxw_drawing_object *drawing_object)
|
||||
{
|
||||
lxw_xml_start_tag(self->file, "xdr:nvSpPr", NULL);
|
||||
|
||||
/* Write the xdr:cNvPr element. */
|
||||
_drawing_write_c_nv_pr(self, "TextBox", index, drawing_object);
|
||||
|
||||
/* Write the xdr:cNvSpPr element. */
|
||||
_drawing_write_c_nv_sp_pr_textbox(self);
|
||||
|
||||
lxw_xml_end_tag(self->file, "xdr:nvSpPr");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <a:prstGeom> element for shapes.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_a_prst_geom_rect(lxw_drawing *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("prst", "rect");
|
||||
|
||||
lxw_xml_start_tag(self->file, "a:prstGeom", &attributes);
|
||||
|
||||
lxw_xml_empty_tag(self->file, "a:avLst", NULL);
|
||||
|
||||
lxw_xml_end_tag(self->file, "a:prstGeom");
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <xdr:spPr> element for shapes.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_sp_pr_shape(lxw_drawing *self, lxw_drawing_object *drawing_object)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
lxw_xml_start_tag(self->file, "xdr:spPr", NULL);
|
||||
|
||||
/* Write the a:xfrm element. */
|
||||
_drawing_write_a_xfrm(self, drawing_object);
|
||||
|
||||
/* Write the a:prstGeom element. */
|
||||
_drawing_write_a_prst_geom_rect(self);
|
||||
|
||||
/* Write the a:solidFill element with scheme color. */
|
||||
lxw_xml_start_tag(self->file, "a:solidFill", NULL);
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("val", "lt1");
|
||||
lxw_xml_empty_tag(self->file, "a:schemeClr", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
lxw_xml_end_tag(self->file, "a:solidFill");
|
||||
|
||||
/* Write the a:ln element with line styling. */
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_INT("w", 9525);
|
||||
LXW_PUSH_ATTRIBUTES_STR("cmpd", "sng");
|
||||
lxw_xml_start_tag(self->file, "a:ln", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
|
||||
/* Write line solid fill with shaded scheme color. */
|
||||
lxw_xml_start_tag(self->file, "a:solidFill", NULL);
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("val", "lt1");
|
||||
lxw_xml_start_tag(self->file, "a:schemeClr", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_INT("val", 50000);
|
||||
lxw_xml_empty_tag(self->file, "a:shade", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
lxw_xml_end_tag(self->file, "a:schemeClr");
|
||||
lxw_xml_end_tag(self->file, "a:solidFill");
|
||||
|
||||
lxw_xml_end_tag(self->file, "a:ln");
|
||||
|
||||
lxw_xml_end_tag(self->file, "xdr:spPr");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <a:t> element for text.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_a_t(lxw_drawing *self, const char *text)
|
||||
{
|
||||
lxw_xml_data_element(self->file, "a:t", text, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <a:rPr> element for text run properties.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_a_r_pr(lxw_drawing *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("lang", "en-US");
|
||||
LXW_PUSH_ATTRIBUTES_INT("sz", 1100);
|
||||
|
||||
lxw_xml_empty_tag(self->file, "a:rPr", &attributes);
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <a:r> element for text run.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_a_r(lxw_drawing *self, const char *text)
|
||||
{
|
||||
lxw_xml_start_tag(self->file, "a:r", NULL);
|
||||
|
||||
/* Write the a:rPr element. */
|
||||
_drawing_write_a_r_pr(self);
|
||||
|
||||
/* Write the a:t element. */
|
||||
_drawing_write_a_t(self, text);
|
||||
|
||||
lxw_xml_end_tag(self->file, "a:r");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <a:pPr> element for paragraph properties.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_a_p_pr(lxw_drawing *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("algn", "l");
|
||||
|
||||
lxw_xml_empty_tag(self->file, "a:pPr", &attributes);
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <a:p> element for paragraph.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_a_p_textbox(lxw_drawing *self, const char *text)
|
||||
{
|
||||
lxw_xml_start_tag(self->file, "a:p", NULL);
|
||||
|
||||
/* Write the a:r element. */
|
||||
_drawing_write_a_r(self, text);
|
||||
|
||||
lxw_xml_end_tag(self->file, "a:p");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <a:bodyPr> element for text body properties.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_a_body_pr(lxw_drawing *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("wrap", "square");
|
||||
LXW_PUSH_ATTRIBUTES_INT("rtlCol", 0);
|
||||
LXW_PUSH_ATTRIBUTES_STR("anchor", "t");
|
||||
|
||||
lxw_xml_empty_tag(self->file, "a:bodyPr", &attributes);
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <xdr:txBody> element for textbox.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_tx_body(lxw_drawing *self, const char *text)
|
||||
{
|
||||
lxw_xml_start_tag(self->file, "xdr:txBody", NULL);
|
||||
|
||||
/* Write the a:bodyPr element. */
|
||||
_drawing_write_a_body_pr(self);
|
||||
|
||||
/* Write the a:lstStyle element. */
|
||||
lxw_xml_empty_tag(self->file, "a:lstStyle", NULL);
|
||||
|
||||
/* Write the a:p element. */
|
||||
_drawing_write_a_p_textbox(self, text);
|
||||
|
||||
lxw_xml_end_tag(self->file, "xdr:txBody");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <xdr:style> element for shapes.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_style(lxw_drawing *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
lxw_xml_start_tag(self->file, "xdr:style", NULL);
|
||||
|
||||
/* Write the a:lnRef element. */
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_INT("idx", 0);
|
||||
lxw_xml_start_tag(self->file, "a:lnRef", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_INT("r", 0);
|
||||
LXW_PUSH_ATTRIBUTES_INT("g", 0);
|
||||
LXW_PUSH_ATTRIBUTES_INT("b", 0);
|
||||
lxw_xml_empty_tag(self->file, "a:scrgbClr", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
lxw_xml_end_tag(self->file, "a:lnRef");
|
||||
|
||||
/* Write the a:fillRef element. */
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_INT("idx", 0);
|
||||
lxw_xml_start_tag(self->file, "a:fillRef", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_INT("r", 0);
|
||||
LXW_PUSH_ATTRIBUTES_INT("g", 0);
|
||||
LXW_PUSH_ATTRIBUTES_INT("b", 0);
|
||||
lxw_xml_empty_tag(self->file, "a:scrgbClr", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
lxw_xml_end_tag(self->file, "a:fillRef");
|
||||
|
||||
/* Write the a:effectRef element. */
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_INT("idx", 0);
|
||||
lxw_xml_start_tag(self->file, "a:effectRef", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_INT("r", 0);
|
||||
LXW_PUSH_ATTRIBUTES_INT("g", 0);
|
||||
LXW_PUSH_ATTRIBUTES_INT("b", 0);
|
||||
lxw_xml_empty_tag(self->file, "a:scrgbClr", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
lxw_xml_end_tag(self->file, "a:effectRef");
|
||||
|
||||
/* Write the a:fontRef element. */
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("idx", "minor");
|
||||
lxw_xml_start_tag(self->file, "a:fontRef", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("val", "dk1");
|
||||
lxw_xml_empty_tag(self->file, "a:schemeClr", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
lxw_xml_end_tag(self->file, "a:fontRef");
|
||||
|
||||
lxw_xml_end_tag(self->file, "xdr:style");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <xdr:sp> element for shapes.
|
||||
*/
|
||||
STATIC void
|
||||
_drawing_write_sp(lxw_drawing *self, uint32_t index,
|
||||
lxw_drawing_object *drawing_object)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("macro", "");
|
||||
LXW_PUSH_ATTRIBUTES_STR("textlink", "");
|
||||
|
||||
lxw_xml_start_tag(self->file, "xdr:sp", &attributes);
|
||||
|
||||
/* Write the xdr:nvSpPr element. */
|
||||
_drawing_write_nv_sp_pr(self, index, drawing_object);
|
||||
|
||||
/* Write the xdr:spPr element. */
|
||||
_drawing_write_sp_pr_shape(self, drawing_object);
|
||||
|
||||
/* Write the xdr:style element. */
|
||||
_drawing_write_style(self);
|
||||
|
||||
/* Write the xdr:txBody element if there is text. */
|
||||
if (drawing_object->text)
|
||||
_drawing_write_tx_body(self, drawing_object->text);
|
||||
|
||||
lxw_xml_end_tag(self->file, "xdr:sp");
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <xdr:clientData> element.
|
||||
*/
|
||||
|
|
@ -842,10 +1161,9 @@ _drawing_write_two_cell_anchor(lxw_drawing *self, uint32_t index,
|
|||
/* Write the xdr:pic element. */
|
||||
_drawing_write_pic(self, index, drawing_object);
|
||||
}
|
||||
else {
|
||||
/* Write the xdr:sp element for shapes. */
|
||||
/* _drawing_write_sp(self, index, col_absolute, row_absolute, width,
|
||||
height, shape); */
|
||||
else if (drawing_object->type == LXW_DRAWING_SHAPE) {
|
||||
/* Write the xdr:sp element for shapes/textboxes. */
|
||||
_drawing_write_sp(self, index, drawing_object);
|
||||
}
|
||||
|
||||
/* Write the xdr:clientData element. */
|
||||
|
|
|
|||
259
src/feature_property_bag.c
Normal file
259
src/feature_property_bag.c
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* libxlsxwriter
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org.
|
||||
*
|
||||
* feature_property_bag - A libxlsxwriter library for creating Excel XLSX
|
||||
* featurePropertyBag files.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter/xmlwriter.h"
|
||||
#include "xlsxwriter/feature_property_bag.h"
|
||||
#include "xlsxwriter/utility.h"
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Private functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Create a new feature_property_bag object.
|
||||
*/
|
||||
lxw_feature_property_bag *
|
||||
lxw_feature_property_bag_new(void)
|
||||
{
|
||||
lxw_feature_property_bag *feature_property_bag =
|
||||
calloc(1, sizeof(lxw_feature_property_bag));
|
||||
GOTO_LABEL_ON_MEM_ERROR(feature_property_bag, mem_error);
|
||||
|
||||
return feature_property_bag;
|
||||
|
||||
mem_error:
|
||||
lxw_feature_property_bag_free(feature_property_bag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a feature_property_bag object.
|
||||
*/
|
||||
void
|
||||
lxw_feature_property_bag_free(lxw_feature_property_bag *feature_property_bag)
|
||||
{
|
||||
if (!feature_property_bag)
|
||||
return;
|
||||
|
||||
free(feature_property_bag);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Write the XML declaration.
|
||||
*/
|
||||
STATIC void
|
||||
_feature_property_bag_xml_declaration(lxw_feature_property_bag *self)
|
||||
{
|
||||
lxw_xml_declaration(self->file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <FeaturePropertyBags> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_feature_property_bags(lxw_feature_property_bag *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("xmlns",
|
||||
"http://schemas.microsoft.com/office/spreadsheetml/2022/featurepropertybag");
|
||||
|
||||
lxw_xml_start_tag(self->file, "FeaturePropertyBags", &attributes);
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the Checkbox <bag> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_checkbox_bag(lxw_feature_property_bag *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("type", "Checkbox");
|
||||
|
||||
lxw_xml_empty_tag(self->file, "bag", &attributes);
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <bagId> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_bag_id(lxw_feature_property_bag *self, const char *key, int id)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
char id_str[LXW_UINT32_T_LENGTH];
|
||||
|
||||
lxw_snprintf(id_str, LXW_UINT32_T_LENGTH, "%d", id);
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
if (key && key[0] != '\0')
|
||||
LXW_PUSH_ATTRIBUTES_STR("k", key);
|
||||
|
||||
lxw_xml_data_element(self->file, "bagId", id_str, &attributes);
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the XFControls <bag> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_xf_controls_bag(lxw_feature_property_bag *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("type", "XFControls");
|
||||
|
||||
lxw_xml_start_tag(self->file, "bag", &attributes);
|
||||
|
||||
_write_bag_id(self, "CellControl", 0);
|
||||
|
||||
lxw_xml_end_tag(self->file, "bag");
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the XFComplement <bag> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_xf_complement_bag(lxw_feature_property_bag *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("type", "XFComplement");
|
||||
|
||||
lxw_xml_start_tag(self->file, "bag", &attributes);
|
||||
|
||||
_write_bag_id(self, "XFControls", 1);
|
||||
|
||||
lxw_xml_end_tag(self->file, "bag");
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the XFComplements <bag> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_xf_complements_bag(lxw_feature_property_bag *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("type", "XFComplements");
|
||||
LXW_PUSH_ATTRIBUTES_STR("extRef", "XFComplementsMapperExtRef");
|
||||
|
||||
lxw_xml_start_tag(self->file, "bag", &attributes);
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("k", "MappedFeaturePropertyBags");
|
||||
lxw_xml_start_tag(self->file, "a", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
|
||||
_write_bag_id(self, NULL, 2);
|
||||
|
||||
lxw_xml_end_tag(self->file, "a");
|
||||
lxw_xml_end_tag(self->file, "bag");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the DXFComplements <bag> element.
|
||||
*/
|
||||
STATIC void
|
||||
_write_dxf_complements_bag(lxw_feature_property_bag *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("type", "DXFComplements");
|
||||
LXW_PUSH_ATTRIBUTES_STR("extRef", "DXFComplementsMapperExtRef");
|
||||
|
||||
lxw_xml_start_tag(self->file, "bag", &attributes);
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("k", "MappedFeaturePropertyBags");
|
||||
lxw_xml_start_tag(self->file, "a", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
|
||||
_write_bag_id(self, NULL, 2);
|
||||
|
||||
lxw_xml_end_tag(self->file, "a");
|
||||
lxw_xml_end_tag(self->file, "bag");
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* XML file assembly functions.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Assemble and write the XML file.
|
||||
*/
|
||||
void
|
||||
lxw_feature_property_bag_assemble_xml_file(lxw_feature_property_bag *self)
|
||||
{
|
||||
/* Write the XML declaration. */
|
||||
_feature_property_bag_xml_declaration(self);
|
||||
|
||||
/* Write the FeaturePropertyBags element. */
|
||||
_write_feature_property_bags(self);
|
||||
|
||||
/* Write the Checkbox bag element. */
|
||||
_write_checkbox_bag(self);
|
||||
|
||||
/* Write the XFControls bag element. */
|
||||
_write_xf_controls_bag(self);
|
||||
|
||||
/* Write the XFComplement bag element. */
|
||||
_write_xf_complement_bag(self);
|
||||
|
||||
/* Write the XFComplements bag element. */
|
||||
_write_xf_complements_bag(self);
|
||||
|
||||
/* Write the DXFComplements bag element if required. */
|
||||
if (self->has_dxf_complements)
|
||||
_write_dxf_complements_bag(self);
|
||||
|
||||
lxw_xml_end_tag(self->file, "FeaturePropertyBags");
|
||||
}
|
||||
11
src/format.c
11
src/format.c
|
|
@ -101,6 +101,8 @@ lxw_format_new(void)
|
|||
|
||||
format->quote_prefix = LXW_FALSE;
|
||||
|
||||
format->checkbox = LXW_FALSE;
|
||||
|
||||
return format;
|
||||
|
||||
mem_error:
|
||||
|
|
@ -830,3 +832,12 @@ format_set_quote_prefix(lxw_format *self)
|
|||
{
|
||||
self->quote_prefix = LXW_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the checkbox property.
|
||||
*/
|
||||
void
|
||||
format_set_checkbox(lxw_format *self)
|
||||
{
|
||||
self->checkbox = LXW_TRUE;
|
||||
}
|
||||
|
|
|
|||
654
src/labview_wrappers.c
Normal file
654
src/labview_wrappers.c
Normal file
|
|
@ -0,0 +1,654 @@
|
|||
/*
|
||||
* labview_wrappers.c - LabVIEW wrapper functions with ANSI to UTF-8 conversion
|
||||
*
|
||||
* These functions wrap the standard libxlsxwriter functions to convert
|
||||
* ANSI-encoded strings (from LabVIEW) to UTF-8 before passing to the library.
|
||||
*
|
||||
* LabVIEW uses unsigned long (32-bit) to represent opaque pointer handles.
|
||||
* These wrapper functions cast between the handle representation and actual pointers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org.
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Handle type for LabVIEW compatibility (32-bit on x86, 64-bit handles need uintptr_t) */
|
||||
typedef uintptr_t lxw_handle;
|
||||
|
||||
/*
|
||||
* Convert ANSI string to UTF-8.
|
||||
* Returns newly allocated UTF-8 string (caller must free) or NULL on failure.
|
||||
*/
|
||||
static char *
|
||||
ansi_to_utf8(const char *ansi_str)
|
||||
{
|
||||
if (!ansi_str || !*ansi_str)
|
||||
return NULL;
|
||||
|
||||
/* First convert ANSI to UTF-16 */
|
||||
int wide_len = MultiByteToWideChar(CP_ACP, 0, ansi_str, -1, NULL, 0);
|
||||
if (wide_len == 0)
|
||||
return NULL;
|
||||
|
||||
wchar_t *wide_str = (wchar_t *)malloc(wide_len * sizeof(wchar_t));
|
||||
if (!wide_str)
|
||||
return NULL;
|
||||
|
||||
if (MultiByteToWideChar(CP_ACP, 0, ansi_str, -1, wide_str, wide_len) == 0) {
|
||||
free(wide_str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Then convert UTF-16 to UTF-8 */
|
||||
int utf8_len = WideCharToMultiByte(CP_UTF8, 0, wide_str, -1, NULL, 0, NULL, NULL);
|
||||
if (utf8_len == 0) {
|
||||
free(wide_str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *utf8_str = (char *)malloc(utf8_len);
|
||||
if (!utf8_str) {
|
||||
free(wide_str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, wide_str, -1, utf8_str, utf8_len, NULL, NULL) == 0) {
|
||||
free(wide_str);
|
||||
free(utf8_str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(wide_str);
|
||||
return utf8_str;
|
||||
}
|
||||
|
||||
#else
|
||||
/* On non-Windows, assume strings are already UTF-8 */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *
|
||||
ansi_to_utf8(const char *str)
|
||||
{
|
||||
if (!str)
|
||||
return NULL;
|
||||
return strdup(str);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ============================================================================
|
||||
* Worksheet write functions
|
||||
* ============================================================================ */
|
||||
|
||||
lxw_error
|
||||
worksheet_write_string_lv(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col,
|
||||
const char *string, lxw_format *format)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(string);
|
||||
lxw_error err = worksheet_write_string(worksheet, row, col, utf8 ? utf8 : string, format);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_write_formula_lv(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col,
|
||||
const char *formula, lxw_format *format)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(formula);
|
||||
lxw_error err = worksheet_write_formula(worksheet, row, col, utf8 ? utf8 : formula, format);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_write_url_lv(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col,
|
||||
const char *url, lxw_format *format)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(url);
|
||||
lxw_error err = worksheet_write_url(worksheet, row, col, utf8 ? utf8 : url, format);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_write_comment_lv(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col,
|
||||
const char *string)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(string);
|
||||
lxw_error err = worksheet_write_comment(worksheet, row, col, utf8 ? utf8 : string);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_set_header_lv(lxw_worksheet *worksheet, const char *header)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(header);
|
||||
lxw_error err = worksheet_set_header(worksheet, utf8 ? utf8 : header);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_set_footer_lv(lxw_worksheet *worksheet, const char *footer)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(footer);
|
||||
lxw_error err = worksheet_set_footer(worksheet, utf8 ? utf8 : footer);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_merge_range_lv(lxw_worksheet *worksheet, lxw_row_t first_row, lxw_col_t first_col,
|
||||
lxw_row_t last_row, lxw_col_t last_col, const char *string,
|
||||
lxw_format *format)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(string);
|
||||
lxw_error err = worksheet_merge_range(worksheet, first_row, first_col, last_row, last_col,
|
||||
utf8 ? utf8 : string, format);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
void
|
||||
worksheet_set_comments_author_lv(lxw_worksheet *worksheet, const char *author)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(author);
|
||||
worksheet_set_comments_author(worksheet, utf8 ? utf8 : author);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_insert_textbox_lv(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col,
|
||||
const char *text)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(text);
|
||||
lxw_error err = worksheet_insert_textbox(worksheet, row, col, utf8 ? utf8 : text);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_insert_textbox_opt_lv(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col,
|
||||
const char *text, lxw_textbox_options *options)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(text);
|
||||
lxw_error err = worksheet_insert_textbox_opt(worksheet, row, col, utf8 ? utf8 : text, options);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Chart functions
|
||||
* ============================================================================ */
|
||||
|
||||
lxw_chart_series *
|
||||
chart_add_series_lv(lxw_chart *chart, const char *categories, const char *values,
|
||||
uint8_t y2_axis)
|
||||
{
|
||||
char *utf8_cat = ansi_to_utf8(categories);
|
||||
char *utf8_val = ansi_to_utf8(values);
|
||||
lxw_chart_series *series = chart_add_series_impl(chart,
|
||||
utf8_cat ? utf8_cat : categories,
|
||||
utf8_val ? utf8_val : values,
|
||||
y2_axis);
|
||||
free(utf8_cat);
|
||||
free(utf8_val);
|
||||
return series;
|
||||
}
|
||||
|
||||
void
|
||||
chart_series_set_name_lv(lxw_chart_series *series, const char *name)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(name);
|
||||
chart_series_set_name(series, utf8 ? utf8 : name);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
chart_axis_set_name_lv(lxw_chart_axis *axis, const char *name)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(name);
|
||||
chart_axis_set_name(axis, utf8 ? utf8 : name);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
chart_title_set_name_lv(lxw_chart *chart, const char *name)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(name);
|
||||
chart_title_set_name(chart, utf8 ? utf8 : name);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
chart_series_set_trendline_name_lv(lxw_chart_series *series, const char *name)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(name);
|
||||
chart_series_set_trendline_name(series, utf8 ? utf8 : name);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
chart_axis_set_num_format_lv(lxw_chart_axis *axis, const char *num_format)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(num_format);
|
||||
chart_axis_set_num_format(axis, utf8 ? utf8 : num_format);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
chart_series_set_labels_num_format_lv(lxw_chart_series *series, const char *num_format)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(num_format);
|
||||
chart_series_set_labels_num_format(series, utf8 ? utf8 : num_format);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
chart_series_set_categories_lv(lxw_chart_series *series, const char *sheetname,
|
||||
lxw_row_t first_row, lxw_col_t first_col,
|
||||
lxw_row_t last_row, lxw_col_t last_col)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(sheetname);
|
||||
chart_series_set_categories(series, utf8 ? utf8 : sheetname,
|
||||
first_row, first_col, last_row, last_col);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
chart_series_set_values_lv(lxw_chart_series *series, const char *sheetname,
|
||||
lxw_row_t first_row, lxw_col_t first_col,
|
||||
lxw_row_t last_row, lxw_col_t last_col)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(sheetname);
|
||||
chart_series_set_values(series, utf8 ? utf8 : sheetname,
|
||||
first_row, first_col, last_row, last_col);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
chart_series_set_name_range_lv(lxw_chart_series *series, const char *sheetname,
|
||||
lxw_row_t row, lxw_col_t col)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(sheetname);
|
||||
chart_series_set_name_range(series, utf8 ? utf8 : sheetname, row, col);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
chart_axis_set_name_range_lv(lxw_chart_axis *axis, const char *sheetname,
|
||||
lxw_row_t row, lxw_col_t col)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(sheetname);
|
||||
chart_axis_set_name_range(axis, utf8 ? utf8 : sheetname, row, col);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
chart_title_set_name_range_lv(lxw_chart *chart, const char *sheetname,
|
||||
lxw_row_t row, lxw_col_t col)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(sheetname);
|
||||
chart_title_set_name_range(chart, utf8 ? utf8 : sheetname, row, col);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Format functions
|
||||
* ============================================================================ */
|
||||
|
||||
void
|
||||
format_set_font_name_lv(lxw_format *format, const char *font_name)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(font_name);
|
||||
format_set_font_name(format, utf8 ? utf8 : font_name);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
void
|
||||
format_set_num_format_lv(lxw_format *format, const char *num_format)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(num_format);
|
||||
format_set_num_format(format, utf8 ? utf8 : num_format);
|
||||
free(utf8);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Workbook functions
|
||||
* ============================================================================ */
|
||||
|
||||
lxw_worksheet *
|
||||
workbook_add_worksheet_lv(lxw_workbook *workbook, const char *sheetname)
|
||||
{
|
||||
/* Pass NULL to get default Sheet1, Sheet2, etc. names */
|
||||
if (!sheetname || !*sheetname) {
|
||||
return workbook_add_worksheet(workbook, NULL);
|
||||
}
|
||||
char *utf8 = ansi_to_utf8(sheetname);
|
||||
lxw_worksheet *ws = workbook_add_worksheet(workbook, utf8 ? utf8 : sheetname);
|
||||
free(utf8);
|
||||
return ws;
|
||||
}
|
||||
|
||||
lxw_chartsheet *
|
||||
workbook_add_chartsheet_lv(lxw_workbook *workbook, const char *sheetname)
|
||||
{
|
||||
/* Pass NULL to get default Chart1, Chart2, etc. names */
|
||||
if (!sheetname || !*sheetname) {
|
||||
return workbook_add_chartsheet(workbook, NULL);
|
||||
}
|
||||
char *utf8 = ansi_to_utf8(sheetname);
|
||||
lxw_chartsheet *cs = workbook_add_chartsheet(workbook, utf8 ? utf8 : sheetname);
|
||||
free(utf8);
|
||||
return cs;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
workbook_define_name_lv(lxw_workbook *workbook, const char *name, const char *formula)
|
||||
{
|
||||
char *utf8_name = ansi_to_utf8(name);
|
||||
char *utf8_formula = ansi_to_utf8(formula);
|
||||
lxw_error err = workbook_define_name(workbook,
|
||||
utf8_name ? utf8_name : name,
|
||||
utf8_formula ? utf8_formula : formula);
|
||||
free(utf8_name);
|
||||
free(utf8_formula);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_worksheet *
|
||||
workbook_get_worksheet_by_name_lv(lxw_workbook *workbook, const char *name)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(name);
|
||||
lxw_worksheet *ws = workbook_get_worksheet_by_name(workbook, utf8 ? utf8 : name);
|
||||
free(utf8);
|
||||
return ws;
|
||||
}
|
||||
|
||||
lxw_chartsheet *
|
||||
workbook_get_chartsheet_by_name_lv(lxw_workbook *workbook, const char *name)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(name);
|
||||
lxw_chartsheet *cs = workbook_get_chartsheet_by_name(workbook, utf8 ? utf8 : name);
|
||||
free(utf8);
|
||||
return cs;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
workbook_validate_sheet_name_lv(lxw_workbook *workbook, const char *sheetname)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(sheetname);
|
||||
lxw_error err = workbook_validate_sheet_name(workbook, utf8 ? utf8 : sheetname);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
workbook_set_custom_property_string_lv(lxw_workbook *workbook, const char *name,
|
||||
const char *value)
|
||||
{
|
||||
char *utf8_name = ansi_to_utf8(name);
|
||||
char *utf8_value = ansi_to_utf8(value);
|
||||
lxw_error err = workbook_set_custom_property_string(workbook,
|
||||
utf8_name ? utf8_name : name,
|
||||
utf8_value ? utf8_value : value);
|
||||
free(utf8_name);
|
||||
free(utf8_value);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Chartsheet functions
|
||||
* ============================================================================ */
|
||||
|
||||
lxw_error
|
||||
chartsheet_set_header_lv(lxw_chartsheet *chartsheet, const char *header)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(header);
|
||||
lxw_error err = chartsheet_set_header(chartsheet, utf8 ? utf8 : header);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
chartsheet_set_footer_lv(lxw_chartsheet *chartsheet, const char *footer)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(footer);
|
||||
lxw_error err = chartsheet_set_footer(chartsheet, utf8 ? utf8 : footer);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* File path functions (ANSI to UTF-8 conversion for lxw_fopen compatibility)
|
||||
* ============================================================================ */
|
||||
|
||||
lxw_workbook *
|
||||
workbook_new_lv(const char *filename)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(filename);
|
||||
lxw_workbook *wb = workbook_new(utf8 ? utf8 : filename);
|
||||
free(utf8);
|
||||
return wb;
|
||||
}
|
||||
|
||||
lxw_workbook *
|
||||
workbook_new_opt_lv(const char *filename, lxw_workbook_options *options)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(filename);
|
||||
lxw_workbook *wb = workbook_new_opt(utf8 ? utf8 : filename, options);
|
||||
free(utf8);
|
||||
return wb;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_insert_image_lv(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col,
|
||||
const char *filename)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(filename);
|
||||
lxw_error err = worksheet_insert_image(worksheet, row, col, utf8 ? utf8 : filename);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_insert_image_opt_lv(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col,
|
||||
const char *filename, lxw_image_options *options)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(filename);
|
||||
lxw_error err = worksheet_insert_image_opt(worksheet, row, col, utf8 ? utf8 : filename, options);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_embed_image_lv(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col,
|
||||
const char *filename)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(filename);
|
||||
lxw_error err = worksheet_embed_image(worksheet, row, col, utf8 ? utf8 : filename);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_embed_image_opt_lv(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col,
|
||||
const char *filename, lxw_image_options *options)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(filename);
|
||||
lxw_error err = worksheet_embed_image_opt(worksheet, row, col, utf8 ? utf8 : filename, options);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_set_background_lv(lxw_worksheet *worksheet, const char *filename)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(filename);
|
||||
lxw_error err = worksheet_set_background(worksheet, utf8 ? utf8 : filename);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
workbook_add_vba_project_lv(lxw_workbook *workbook, const char *filename)
|
||||
{
|
||||
char *utf8 = ansi_to_utf8(filename);
|
||||
lxw_error err = workbook_add_vba_project(workbook, utf8 ? utf8 : filename);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
|
||||
lxw_error
|
||||
workbook_add_signed_vba_project_lv(lxw_workbook *workbook, const char *vba_project,
|
||||
const char *signature)
|
||||
{
|
||||
char *utf8_vba = ansi_to_utf8(vba_project);
|
||||
char *utf8_sig = ansi_to_utf8(signature);
|
||||
lxw_error err = workbook_add_signed_vba_project(workbook,
|
||||
utf8_vba ? utf8_vba : vba_project,
|
||||
utf8_sig ? utf8_sig : signature);
|
||||
free(utf8_vba);
|
||||
free(utf8_sig);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Autofilter functions
|
||||
* ============================================================================ */
|
||||
|
||||
lxw_error
|
||||
worksheet_filter_column_lv(lxw_worksheet *worksheet, lxw_col_t col,
|
||||
uint8_t criteria, const char *value_string, double value)
|
||||
{
|
||||
lxw_filter_rule rule = {0};
|
||||
rule.criteria = criteria;
|
||||
rule.value = value;
|
||||
|
||||
if (value_string && *value_string) {
|
||||
char *utf8 = ansi_to_utf8(value_string);
|
||||
rule.value_string = utf8 ? utf8 : value_string;
|
||||
lxw_error err = worksheet_filter_column(worksheet, col, &rule);
|
||||
free(utf8);
|
||||
return err;
|
||||
}
|
||||
else {
|
||||
rule.value_string = NULL;
|
||||
return worksheet_filter_column(worksheet, col, &rule);
|
||||
}
|
||||
}
|
||||
|
||||
lxw_error
|
||||
worksheet_filter_column2_lv(lxw_worksheet *worksheet, lxw_col_t col,
|
||||
uint8_t criteria1, const char *value_string1, double value1,
|
||||
uint8_t criteria2, const char *value_string2, double value2,
|
||||
uint8_t and_or)
|
||||
{
|
||||
lxw_filter_rule rule1 = {0};
|
||||
lxw_filter_rule rule2 = {0};
|
||||
char *utf8_1 = NULL;
|
||||
char *utf8_2 = NULL;
|
||||
|
||||
rule1.criteria = criteria1;
|
||||
rule1.value = value1;
|
||||
rule2.criteria = criteria2;
|
||||
rule2.value = value2;
|
||||
|
||||
if (value_string1 && *value_string1) {
|
||||
utf8_1 = ansi_to_utf8(value_string1);
|
||||
rule1.value_string = utf8_1 ? utf8_1 : value_string1;
|
||||
}
|
||||
|
||||
if (value_string2 && *value_string2) {
|
||||
utf8_2 = ansi_to_utf8(value_string2);
|
||||
rule2.value_string = utf8_2 ? utf8_2 : value_string2;
|
||||
}
|
||||
|
||||
lxw_error err = worksheet_filter_column2(worksheet, col, &rule1, &rule2, and_or);
|
||||
|
||||
free(utf8_1);
|
||||
free(utf8_2);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Chart data label functions
|
||||
* ============================================================================ */
|
||||
|
||||
lxw_error
|
||||
chart_series_set_labels_custom_lv(lxw_chart_series *series,
|
||||
uintptr_t *values,
|
||||
uint8_t *hide_flags,
|
||||
uint16_t count)
|
||||
{
|
||||
lxw_error err = LXW_NO_ERROR;
|
||||
uint16_t i;
|
||||
lxw_chart_data_label *labels = NULL;
|
||||
lxw_chart_data_label **label_ptrs = NULL;
|
||||
char **utf8_values = NULL;
|
||||
|
||||
if (!series || count == 0)
|
||||
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
||||
|
||||
/* Allocate arrays */
|
||||
labels = (lxw_chart_data_label *)calloc(count, sizeof(lxw_chart_data_label));
|
||||
label_ptrs = (lxw_chart_data_label **)calloc(count + 1, sizeof(lxw_chart_data_label *));
|
||||
utf8_values = (char **)calloc(count, sizeof(char *));
|
||||
|
||||
if (!labels || !label_ptrs || !utf8_values) {
|
||||
free(labels);
|
||||
free(label_ptrs);
|
||||
free(utf8_values);
|
||||
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
||||
}
|
||||
|
||||
/* Build the label structs */
|
||||
for (i = 0; i < count; i++) {
|
||||
const char *str;
|
||||
|
||||
/* Set up pointer array */
|
||||
label_ptrs[i] = &labels[i];
|
||||
|
||||
/* Get string pointer from uintptr_t array */
|
||||
str = (values && values[i]) ? (const char *)values[i] : NULL;
|
||||
|
||||
/* Convert value string if provided */
|
||||
if (str && str[0]) {
|
||||
utf8_values[i] = ansi_to_utf8(str);
|
||||
labels[i].value = utf8_values[i] ? utf8_values[i] : str;
|
||||
}
|
||||
else {
|
||||
labels[i].value = NULL;
|
||||
}
|
||||
|
||||
/* Set hide flag */
|
||||
if (hide_flags) {
|
||||
labels[i].hide = hide_flags[i];
|
||||
}
|
||||
|
||||
/* Other fields remain NULL (font, line, fill, pattern) */
|
||||
}
|
||||
|
||||
/* NULL-terminate the pointer array */
|
||||
label_ptrs[count] = NULL;
|
||||
|
||||
/* Call the library function */
|
||||
err = chart_series_set_labels_custom(series, label_ptrs);
|
||||
|
||||
/* Free allocated memory */
|
||||
for (i = 0; i < count; i++) {
|
||||
free(utf8_values[i]);
|
||||
}
|
||||
free(utf8_values);
|
||||
free(labels);
|
||||
free(label_ptrs);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1276,6 +1276,48 @@ mem_error:
|
|||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the featurePropertyBag.xml file.
|
||||
*/
|
||||
STATIC lxw_error
|
||||
_write_feature_property_bag_file(lxw_packager *self)
|
||||
{
|
||||
lxw_error err = LXW_NO_ERROR;
|
||||
lxw_feature_property_bag *feature_property_bag;
|
||||
char *buffer = NULL;
|
||||
size_t buffer_size = 0;
|
||||
|
||||
if (!self->workbook->has_feature_property_bags)
|
||||
return LXW_NO_ERROR;
|
||||
|
||||
feature_property_bag = lxw_feature_property_bag_new();
|
||||
|
||||
if (!feature_property_bag) {
|
||||
err = LXW_ERROR_MEMORY_MALLOC_FAILED;
|
||||
goto mem_error;
|
||||
}
|
||||
|
||||
feature_property_bag->file =
|
||||
lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
||||
if (!feature_property_bag->file) {
|
||||
err = LXW_ERROR_CREATING_TMPFILE;
|
||||
goto mem_error;
|
||||
}
|
||||
|
||||
lxw_feature_property_bag_assemble_xml_file(feature_property_bag);
|
||||
|
||||
err = _add_to_zip(self, feature_property_bag->file, &buffer, &buffer_size,
|
||||
"xl/featurePropertyBag/featurePropertyBag.xml");
|
||||
|
||||
fclose(feature_property_bag->file);
|
||||
free(buffer);
|
||||
|
||||
mem_error:
|
||||
lxw_feature_property_bag_free(feature_property_bag);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the custom.xml file.
|
||||
*/
|
||||
|
|
@ -1539,6 +1581,9 @@ _write_content_types_file(lxw_packager *self)
|
|||
if (workbook->has_embedded_images)
|
||||
lxw_ct_add_rich_value(content_types);
|
||||
|
||||
if (workbook->has_feature_property_bags)
|
||||
lxw_ct_add_feature_property_bag(content_types);
|
||||
|
||||
lxw_content_types_assemble_xml_file(content_types);
|
||||
|
||||
err = _add_to_zip(self, content_types->file, &buffer, &buffer_size,
|
||||
|
|
@ -1612,6 +1657,9 @@ _write_workbook_rels_file(lxw_packager *self)
|
|||
if (workbook->has_embedded_images)
|
||||
lxw_add_rich_value_relationship(rels);
|
||||
|
||||
if (workbook->has_feature_property_bags)
|
||||
lxw_add_feature_property_bag_relationship(rels);
|
||||
|
||||
lxw_relationships_assemble_xml_file(rels);
|
||||
|
||||
err = _add_to_zip(self, rels->file, &buffer, &buffer_size,
|
||||
|
|
@ -2250,6 +2298,9 @@ lxw_create_package(lxw_packager *self)
|
|||
error = _write_rich_value_structure_file(self);
|
||||
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
||||
|
||||
error = _write_feature_property_bag_file(self);
|
||||
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
||||
|
||||
error = _write_rich_value_rels_file(self);
|
||||
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
||||
|
||||
|
|
|
|||
|
|
@ -267,3 +267,15 @@ lxw_add_rich_value_relationship(lxw_relationships *self)
|
|||
NULL);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a featurePropertyBag relationship to workbook .rels xml files.
|
||||
*/
|
||||
void
|
||||
lxw_add_feature_property_bag_relationship(lxw_relationships *self)
|
||||
{
|
||||
_add_relationship(self,
|
||||
"http://schemas.microsoft.com/office/2022/11/relationships/",
|
||||
"FeaturePropertyBag",
|
||||
"featurePropertyBag/featurePropertyBag.xml", NULL);
|
||||
}
|
||||
|
|
|
|||
34
src/styles.c
34
src/styles.c
|
|
@ -1187,6 +1187,34 @@ _write_protection(lxw_styles *self, lxw_format *format)
|
|||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the xfComplement <extLst> elements for checkbox formats.
|
||||
*/
|
||||
STATIC void
|
||||
_write_xf_format_extensions(lxw_styles *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
|
||||
lxw_xml_start_tag(self->file, "extLst", NULL);
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("uri", "{C7286773-470A-42A8-94C5-96B5CB345126}");
|
||||
LXW_PUSH_ATTRIBUTES_STR("xmlns:xfpb",
|
||||
"http://schemas.microsoft.com/office/spreadsheetml/2022/featurepropertybag");
|
||||
|
||||
lxw_xml_start_tag(self->file, "ext", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("i", "0");
|
||||
lxw_xml_empty_tag(self->file, "xfpb:xfComplement", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
|
||||
lxw_xml_end_tag(self->file, "ext");
|
||||
lxw_xml_end_tag(self->file, "extLst");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <xf> element.
|
||||
*/
|
||||
|
|
@ -1198,6 +1226,7 @@ _write_xf(lxw_styles *self, lxw_format *format)
|
|||
uint8_t has_protection = (!format->locked) | format->hidden;
|
||||
uint8_t has_alignment = _has_alignment(format);
|
||||
uint8_t apply_alignment = _apply_alignment(format);
|
||||
uint8_t has_checkbox = format->checkbox;
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_INT("numFmtId", format->num_format_index);
|
||||
|
|
@ -1232,7 +1261,7 @@ _write_xf(lxw_styles *self, lxw_format *format)
|
|||
LXW_PUSH_ATTRIBUTES_STR("applyProtection", "1");
|
||||
|
||||
/* Write XF with sub-elements if required. */
|
||||
if (has_alignment || has_protection) {
|
||||
if (has_alignment || has_protection || has_checkbox) {
|
||||
lxw_xml_start_tag(self->file, "xf", &attributes);
|
||||
|
||||
if (has_alignment)
|
||||
|
|
@ -1241,6 +1270,9 @@ _write_xf(lxw_styles *self, lxw_format *format)
|
|||
if (has_protection)
|
||||
_write_protection(self, format);
|
||||
|
||||
if (has_checkbox)
|
||||
_write_xf_format_extensions(self);
|
||||
|
||||
lxw_xml_end_tag(self->file, "xf");
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
162
src/utility.c
162
src/utility.c
|
|
@ -41,7 +41,7 @@ char *error_strings[LXW_MAX_ERRNO + 1] = {
|
|||
"NULL function parameter ignored.",
|
||||
"Function parameter validation error.",
|
||||
"Function string parameter is empty.",
|
||||
"Datetime struct parameter has an invalid field value.",
|
||||
"A lxw_datetime parameter has a validation error.",
|
||||
"Worksheet name exceeds Excel's limit of 31 characters.",
|
||||
"Worksheet name cannot contain invalid characters: '[ ] : * ? / \\'",
|
||||
"Worksheet name cannot start or end with an apostrophe.",
|
||||
|
|
@ -333,6 +333,9 @@ lxw_name_to_col_2(const char *col_str)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate a lxw_datetime struct.
|
||||
*/
|
||||
lxw_error
|
||||
lxw_datetime_validate(lxw_datetime *datetime)
|
||||
{
|
||||
|
|
@ -749,6 +752,163 @@ lxw_hash_password(const char *password)
|
|||
return hash;
|
||||
}
|
||||
|
||||
/*
|
||||
* Character widths for Calibri 11 font, used for autofit calculations.
|
||||
* Index 0 = space (ASCII 32), through index 94 = tilde (ASCII 126).
|
||||
* Unhandled characters (including UTF-8) default to width 8.
|
||||
*/
|
||||
static const uint8_t char_widths[95] = {
|
||||
3, /* space */
|
||||
5, /* ! */
|
||||
6, /* " */
|
||||
7, /* # */
|
||||
7, /* $ */
|
||||
11, /* % */
|
||||
10, /* & */
|
||||
3, /* ' */
|
||||
5, /* ( */
|
||||
5, /* ) */
|
||||
7, /* * */
|
||||
7, /* + */
|
||||
4, /* , */
|
||||
5, /* - */
|
||||
4, /* . */
|
||||
6, /* / */
|
||||
7, /* 0 */
|
||||
7, /* 1 */
|
||||
7, /* 2 */
|
||||
7, /* 3 */
|
||||
7, /* 4 */
|
||||
7, /* 5 */
|
||||
7, /* 6 */
|
||||
7, /* 7 */
|
||||
7, /* 8 */
|
||||
7, /* 9 */
|
||||
4, /* : */
|
||||
4, /* ; */
|
||||
7, /* < */
|
||||
7, /* = */
|
||||
7, /* > */
|
||||
7, /* ? */
|
||||
13, /* @ */
|
||||
9, /* A */
|
||||
8, /* B */
|
||||
8, /* C */
|
||||
9, /* D */
|
||||
7, /* E */
|
||||
7, /* F */
|
||||
9, /* G */
|
||||
9, /* H */
|
||||
4, /* I */
|
||||
5, /* J */
|
||||
8, /* K */
|
||||
6, /* L */
|
||||
12, /* M */
|
||||
10, /* N */
|
||||
10, /* O */
|
||||
8, /* P */
|
||||
10, /* Q */
|
||||
8, /* R */
|
||||
7, /* S */
|
||||
7, /* T */
|
||||
9, /* U */
|
||||
9, /* V */
|
||||
13, /* W */
|
||||
8, /* X */
|
||||
7, /* Y */
|
||||
7, /* Z */
|
||||
5, /* [ */
|
||||
6, /* backslash */
|
||||
5, /* ] */
|
||||
7, /* ^ */
|
||||
7, /* _ */
|
||||
4, /* ` */
|
||||
7, /* a */
|
||||
8, /* b */
|
||||
6, /* c */
|
||||
8, /* d */
|
||||
8, /* e */
|
||||
5, /* f */
|
||||
7, /* g */
|
||||
8, /* h */
|
||||
4, /* i */
|
||||
4, /* j */
|
||||
7, /* k */
|
||||
4, /* l */
|
||||
12, /* m */
|
||||
8, /* n */
|
||||
8, /* o */
|
||||
8, /* p */
|
||||
8, /* q */
|
||||
5, /* r */
|
||||
6, /* s */
|
||||
5, /* t */
|
||||
8, /* u */
|
||||
7, /* v */
|
||||
11, /* w */
|
||||
7, /* x */
|
||||
7, /* y */
|
||||
6, /* z */
|
||||
5, /* { */
|
||||
7, /* | */
|
||||
5, /* } */
|
||||
7 /* ~ */
|
||||
};
|
||||
|
||||
/*
|
||||
* Calculate the pixel width of a string based on character widths.
|
||||
*/
|
||||
uint16_t
|
||||
lxw_pixel_width(const char *string)
|
||||
{
|
||||
uint16_t length = 0;
|
||||
unsigned char c;
|
||||
|
||||
if (string == NULL || *string == '\0')
|
||||
return 0;
|
||||
|
||||
while ((c = (unsigned char) *string++) != '\0') {
|
||||
/* Check if character is in the printable ASCII range (32-126) */
|
||||
if (c >= 32 && c <= 126) {
|
||||
length += char_widths[c - 32];
|
||||
}
|
||||
else {
|
||||
/* Default width for non-ASCII characters (UTF-8, etc.) */
|
||||
length += 8;
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the column width required to autofit a string.
|
||||
*/
|
||||
double
|
||||
lxw_autofit_width(const char *string)
|
||||
{
|
||||
uint16_t pixels;
|
||||
double width;
|
||||
const double max_digit_width = 7.0; /* For Calibri 11 */
|
||||
const double padding = 5.0;
|
||||
|
||||
if (string == NULL || *string == '\0')
|
||||
return 0.0;
|
||||
|
||||
/* Get pixel width and add 7 pixels padding like Excel */
|
||||
pixels = lxw_pixel_width(string) + 7;
|
||||
|
||||
/* Convert pixels to column width using Excel's formula */
|
||||
if (pixels <= 12) {
|
||||
width = (double) pixels / (max_digit_width + padding);
|
||||
}
|
||||
else {
|
||||
width = ((double) pixels - padding) / max_digit_width;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
/* Make a simple portable version of fopen() for Windows. */
|
||||
#ifdef __MINGW32__
|
||||
#undef _WIN32
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#include "xlsxwriter/utility.h"
|
||||
#include "xlsxwriter/packager.h"
|
||||
#include "xlsxwriter/hash_table.h"
|
||||
#include "xlsxwriter/hash_table.h"
|
||||
|
||||
STATIC int _worksheet_name_cmp(lxw_worksheet_name *name1,
|
||||
lxw_worksheet_name *name2);
|
||||
|
|
@ -300,8 +299,8 @@ lxw_workbook_set_default_xf_indices(lxw_workbook *self)
|
|||
|
||||
STAILQ_FOREACH(format, self->formats, list_pointers) {
|
||||
|
||||
/* Skip the hyperlink format. */
|
||||
if (index != 1)
|
||||
/* Skip the hyperlink format (index 1) and checkbox format (index 2). */
|
||||
if (index != 1 && index != 2)
|
||||
lxw_format_get_xf_index(format);
|
||||
|
||||
index++;
|
||||
|
|
@ -1038,6 +1037,8 @@ _add_chart_cache_data(lxw_workbook *self)
|
|||
_populate_range(self, chart->title.range);
|
||||
_populate_range(self, chart->x_axis->title.range);
|
||||
_populate_range(self, chart->y_axis->title.range);
|
||||
_populate_range(self, chart->x2_axis->title.range);
|
||||
_populate_range(self, chart->y2_axis->title.range);
|
||||
|
||||
if (STAILQ_EMPTY(chart->series_list))
|
||||
continue;
|
||||
|
|
@ -1052,6 +1053,31 @@ _add_chart_cache_data(lxw_workbook *self)
|
|||
_populate_range(self, data_label->range);
|
||||
}
|
||||
}
|
||||
|
||||
/* Also populate data for combined charts. */
|
||||
if (chart->combined) {
|
||||
lxw_chart *combined = chart->combined;
|
||||
|
||||
_populate_range(self, combined->title.range);
|
||||
_populate_range(self, combined->x_axis->title.range);
|
||||
_populate_range(self, combined->y_axis->title.range);
|
||||
_populate_range(self, combined->x2_axis->title.range);
|
||||
_populate_range(self, combined->y2_axis->title.range);
|
||||
|
||||
if (!STAILQ_EMPTY(combined->series_list)) {
|
||||
STAILQ_FOREACH(series, combined->series_list, list_pointers) {
|
||||
_populate_range(self, series->categories);
|
||||
_populate_range(self, series->values);
|
||||
_populate_range(self, series->title.range);
|
||||
|
||||
for (i = 0; i < series->data_label_count; i++) {
|
||||
lxw_chart_custom_label *data_label =
|
||||
&series->data_labels[i];
|
||||
_populate_range(self, data_label->range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1106,6 +1132,7 @@ _prepare_drawings(lxw_workbook *self)
|
|||
if (STAILQ_EMPTY(worksheet->image_props)
|
||||
&& STAILQ_EMPTY(worksheet->embedded_image_props)
|
||||
&& STAILQ_EMPTY(worksheet->chart_data)
|
||||
&& STAILQ_EMPTY(worksheet->textbox_data)
|
||||
&& !worksheet->has_header_vml && !worksheet->has_background_image) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1243,6 +1270,11 @@ _prepare_drawings(lxw_workbook *self)
|
|||
ordered_list_pointers);
|
||||
}
|
||||
|
||||
/* Prepare worksheet textboxes. */
|
||||
STAILQ_FOREACH(object_props, worksheet->textbox_data, list_pointers) {
|
||||
lxw_worksheet_prepare_textbox(worksheet, drawing_id, object_props);
|
||||
}
|
||||
|
||||
/* Prepare worksheet header/footer images. */
|
||||
for (i = 0; i < LXW_HEADER_FOOTER_OBJS_MAX; i++) {
|
||||
|
||||
|
|
@ -1968,6 +2000,12 @@ workbook_new_opt(const char *filename, lxw_workbook_options *options)
|
|||
format_set_hyperlink(format);
|
||||
workbook->default_url_format = format;
|
||||
|
||||
/* Add the default checkbox format. */
|
||||
format = workbook_add_format(workbook);
|
||||
GOTO_LABEL_ON_MEM_ERROR(format, mem_error);
|
||||
format_set_checkbox(format);
|
||||
workbook->checkbox_format = format;
|
||||
|
||||
if (options) {
|
||||
workbook->options.constant_memory = options->constant_memory;
|
||||
workbook->options.tmpdir = lxw_strdup(options->tmpdir);
|
||||
|
|
@ -2039,6 +2077,7 @@ workbook_add_worksheet(lxw_workbook *self, const char *sheetname)
|
|||
init_data.first_sheet = &self->first_sheet;
|
||||
init_data.tmpdir = self->options.tmpdir;
|
||||
init_data.default_url_format = self->default_url_format;
|
||||
init_data.checkbox_format = self->checkbox_format;
|
||||
init_data.max_url_length = self->max_url_length;
|
||||
init_data.use_1904_epoch = self->use_1904_epoch;
|
||||
|
||||
|
|
@ -2167,7 +2206,7 @@ workbook_add_chart(lxw_workbook *self, uint8_t type)
|
|||
{
|
||||
lxw_chart *chart;
|
||||
|
||||
if (type == LXW_CHART_NONE || type > LXW_CHART_RADAR_FILLED) {
|
||||
if (type == LXW_CHART_NONE || type > LXW_CHART_STOCK) {
|
||||
LXW_WARN_FORMAT1("workbook_add_chart(): invalid chart type: %d",
|
||||
type);
|
||||
return NULL;
|
||||
|
|
@ -2247,6 +2286,9 @@ workbook_close(lxw_workbook *self)
|
|||
self->has_metadata = LXW_TRUE;
|
||||
self->has_embedded_images = LXW_TRUE;
|
||||
}
|
||||
|
||||
if (worksheet->has_checkboxes)
|
||||
self->has_feature_property_bags = LXW_TRUE;
|
||||
}
|
||||
|
||||
/* Set workbook and worksheet VBA codenames if a macro has been added. */
|
||||
|
|
|
|||
543
src/worksheet.c
543
src/worksheet.c
|
|
@ -151,6 +151,10 @@ lxw_worksheet_new(lxw_worksheet_init_data *init_data)
|
|||
GOTO_LABEL_ON_MEM_ERROR(worksheet->chart_data, mem_error);
|
||||
STAILQ_INIT(worksheet->chart_data);
|
||||
|
||||
worksheet->textbox_data = calloc(1, sizeof(struct lxw_textbox_props));
|
||||
GOTO_LABEL_ON_MEM_ERROR(worksheet->textbox_data, mem_error);
|
||||
STAILQ_INIT(worksheet->textbox_data);
|
||||
|
||||
worksheet->comment_objs = calloc(1, sizeof(struct lxw_comment_objs));
|
||||
GOTO_LABEL_ON_MEM_ERROR(worksheet->comment_objs, mem_error);
|
||||
STAILQ_INIT(worksheet->comment_objs);
|
||||
|
|
@ -176,6 +180,10 @@ lxw_worksheet_new(lxw_worksheet_init_data *init_data)
|
|||
GOTO_LABEL_ON_MEM_ERROR(worksheet->table_objs, mem_error);
|
||||
STAILQ_INIT(worksheet->table_objs);
|
||||
|
||||
worksheet->sparklines = calloc(1, sizeof(struct lxw_sparklines));
|
||||
GOTO_LABEL_ON_MEM_ERROR(worksheet->sparklines, mem_error);
|
||||
STAILQ_INIT(worksheet->sparklines);
|
||||
|
||||
worksheet->external_hyperlinks = calloc(1, sizeof(struct lxw_rel_tuples));
|
||||
GOTO_LABEL_ON_MEM_ERROR(worksheet->external_hyperlinks, mem_error);
|
||||
STAILQ_INIT(worksheet->external_hyperlinks);
|
||||
|
|
@ -293,6 +301,7 @@ lxw_worksheet_new(lxw_worksheet_init_data *init_data)
|
|||
worksheet->active_sheet = init_data->active_sheet;
|
||||
worksheet->first_sheet = init_data->first_sheet;
|
||||
worksheet->default_url_format = init_data->default_url_format;
|
||||
worksheet->checkbox_format = init_data->checkbox_format;
|
||||
worksheet->max_url_length = init_data->max_url_length;
|
||||
worksheet->use_1904_epoch = init_data->use_1904_epoch;
|
||||
}
|
||||
|
|
@ -427,6 +436,7 @@ _free_object_properties(lxw_object_properties *object_property)
|
|||
free(object_property->image_buffer);
|
||||
free(object_property->md5);
|
||||
free(object_property->image_position);
|
||||
free(object_property->text);
|
||||
free(object_property);
|
||||
object_property = NULL;
|
||||
}
|
||||
|
|
@ -635,6 +645,16 @@ lxw_worksheet_free(lxw_worksheet *worksheet)
|
|||
free(worksheet->chart_data);
|
||||
}
|
||||
|
||||
if (worksheet->textbox_data) {
|
||||
while (!STAILQ_EMPTY(worksheet->textbox_data)) {
|
||||
object_props = STAILQ_FIRST(worksheet->textbox_data);
|
||||
STAILQ_REMOVE_HEAD(worksheet->textbox_data, list_pointers);
|
||||
_free_object_properties(object_props);
|
||||
}
|
||||
|
||||
free(worksheet->textbox_data);
|
||||
}
|
||||
|
||||
/* Just free the list. The list objects are freed from the RB tree. */
|
||||
free(worksheet->comment_objs);
|
||||
|
||||
|
|
@ -678,6 +698,20 @@ lxw_worksheet_free(lxw_worksheet *worksheet)
|
|||
free(worksheet->table_objs);
|
||||
}
|
||||
|
||||
if (worksheet->sparklines) {
|
||||
lxw_sparkline *sparkline;
|
||||
while (!STAILQ_EMPTY(worksheet->sparklines)) {
|
||||
sparkline = STAILQ_FIRST(worksheet->sparklines);
|
||||
STAILQ_REMOVE_HEAD(worksheet->sparklines, list_pointers);
|
||||
free(sparkline->range);
|
||||
free(sparkline->location);
|
||||
free(sparkline->date_axis);
|
||||
free(sparkline);
|
||||
}
|
||||
|
||||
free(worksheet->sparklines);
|
||||
}
|
||||
|
||||
if (worksheet->data_validations) {
|
||||
while (!STAILQ_EMPTY(worksheet->data_validations)) {
|
||||
data_validation = STAILQ_FIRST(worksheet->data_validations);
|
||||
|
|
@ -3007,15 +3041,13 @@ _worksheet_position_object_pixels(lxw_worksheet *self,
|
|||
height = height + y1;
|
||||
|
||||
/* Subtract the underlying cell widths to find the end cell. */
|
||||
while (width >= _worksheet_size_col(self, col_end, anchor)
|
||||
&& col_end < LXW_COL_MAX) {
|
||||
while (width >= _worksheet_size_col(self, col_end, anchor)) {
|
||||
width -= _worksheet_size_col(self, col_end, anchor);
|
||||
col_end++;
|
||||
}
|
||||
|
||||
/* Subtract the underlying cell heights to find the end cell. */
|
||||
while (height >= _worksheet_size_row(self, row_end, anchor)
|
||||
&& row_end < LXW_ROW_MAX) {
|
||||
while (height >= _worksheet_size_row(self, row_end, anchor)) {
|
||||
height -= _worksheet_size_row(self, row_end, anchor);
|
||||
row_end++;
|
||||
}
|
||||
|
|
@ -3705,6 +3737,83 @@ mem_error:
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up a textbox in the worksheet.
|
||||
*/
|
||||
void
|
||||
lxw_worksheet_prepare_textbox(lxw_worksheet *self,
|
||||
uint32_t drawing_id,
|
||||
lxw_object_properties *object_props)
|
||||
{
|
||||
lxw_drawing_object *drawing_object;
|
||||
lxw_rel_tuple *relationship;
|
||||
double width;
|
||||
double height;
|
||||
char filename[LXW_FILENAME_LENGTH];
|
||||
|
||||
if (!self->drawing) {
|
||||
self->drawing = lxw_drawing_new();
|
||||
RETURN_VOID_ON_MEM_ERROR(self->drawing);
|
||||
self->drawing->embedded = LXW_TRUE;
|
||||
|
||||
relationship = calloc(1, sizeof(lxw_rel_tuple));
|
||||
RETURN_VOID_ON_MEM_ERROR(relationship);
|
||||
|
||||
relationship->type = lxw_strdup("/drawing");
|
||||
GOTO_LABEL_ON_MEM_ERROR(relationship->type, mem_error);
|
||||
|
||||
lxw_snprintf(filename, LXW_FILENAME_LENGTH,
|
||||
"../drawings/drawing%d.xml", drawing_id);
|
||||
|
||||
relationship->target = lxw_strdup(filename);
|
||||
GOTO_LABEL_ON_MEM_ERROR(relationship->target, mem_error);
|
||||
|
||||
STAILQ_INSERT_TAIL(self->external_drawing_links, relationship,
|
||||
list_pointers);
|
||||
}
|
||||
|
||||
drawing_object = calloc(1, sizeof(lxw_drawing_object));
|
||||
RETURN_VOID_ON_MEM_ERROR(drawing_object);
|
||||
|
||||
drawing_object->anchor = LXW_OBJECT_MOVE_AND_SIZE;
|
||||
if (object_props->object_position)
|
||||
drawing_object->anchor = object_props->object_position;
|
||||
|
||||
drawing_object->type = LXW_DRAWING_SHAPE;
|
||||
drawing_object->description = lxw_strdup(object_props->description);
|
||||
drawing_object->tip = NULL;
|
||||
drawing_object->rel_index = 0;
|
||||
drawing_object->url_rel_index = 0;
|
||||
drawing_object->decorative = object_props->decorative;
|
||||
drawing_object->text = lxw_strdup(object_props->text);
|
||||
|
||||
/* Scale to user scale. */
|
||||
width = object_props->width * object_props->x_scale;
|
||||
height = object_props->height * object_props->y_scale;
|
||||
|
||||
/* Convert to the nearest pixel. */
|
||||
object_props->width = width;
|
||||
object_props->height = height;
|
||||
|
||||
_worksheet_position_object_emus(self, object_props, drawing_object);
|
||||
|
||||
/* Convert from pixels to emus. */
|
||||
drawing_object->width = (uint32_t) (0.5 + width * 9525);
|
||||
drawing_object->height = (uint32_t) (0.5 + height * 9525);
|
||||
|
||||
lxw_add_drawing_object(self->drawing, drawing_object);
|
||||
|
||||
return;
|
||||
|
||||
mem_error:
|
||||
if (relationship) {
|
||||
free(relationship->type);
|
||||
free(relationship->target);
|
||||
free(relationship->target_mode);
|
||||
free(relationship);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up VML objects, such as comments, in the worksheet.
|
||||
*/
|
||||
|
|
@ -7156,6 +7265,217 @@ _worksheet_write_conditional_formatting_2010(lxw_worksheet *self, lxw_cond_forma
|
|||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a sparkline color element like <x14:colorSeries>.
|
||||
* Color of 0 (LXW_COLOR_UNSET) means "not set, use default".
|
||||
*/
|
||||
STATIC void
|
||||
_worksheet_write_sparkline_color(lxw_worksheet *self, const char *tag,
|
||||
lxw_color_t color)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
char rgb_str[LXW_ATTR_32];
|
||||
|
||||
/* 0 means not set, use Excel's default for this style. */
|
||||
if (color == 0)
|
||||
return;
|
||||
|
||||
lxw_snprintf(rgb_str, LXW_ATTR_32, "FF%06X", color & LXW_COLOR_MASK);
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("rgb", rgb_str);
|
||||
lxw_xml_empty_tag(self->file, tag, &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <x14:sparklineGroup> element.
|
||||
*/
|
||||
STATIC void
|
||||
_worksheet_write_sparkline_group(lxw_worksheet *self, lxw_sparkline *sparkline)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
char double_str[LXW_ATTR_32];
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
|
||||
/* Write manualMax if custom max. */
|
||||
if (sparkline->max_axis_type == LXW_SPARKLINE_AXIS_CUSTOM) {
|
||||
lxw_sprintf_dbl(double_str, sparkline->max);
|
||||
LXW_PUSH_ATTRIBUTES_STR("manualMax", double_str);
|
||||
}
|
||||
|
||||
/* Write manualMin if custom min. */
|
||||
if (sparkline->min_axis_type == LXW_SPARKLINE_AXIS_CUSTOM) {
|
||||
lxw_sprintf_dbl(double_str, sparkline->min);
|
||||
LXW_PUSH_ATTRIBUTES_STR("manualMin", double_str);
|
||||
}
|
||||
|
||||
/* Write lineWeight (default is 0.75 but we always write if non-default). */
|
||||
if (sparkline->weight != 0.75) {
|
||||
lxw_sprintf_dbl(double_str, sparkline->weight);
|
||||
LXW_PUSH_ATTRIBUTES_STR("lineWeight", double_str);
|
||||
}
|
||||
|
||||
/* Write type (line is default, so only write column or win/loss). */
|
||||
if (sparkline->type == LXW_SPARKLINE_COLUMN) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("type", "column");
|
||||
}
|
||||
else if (sparkline->type == LXW_SPARKLINE_WIN_LOSS) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("type", "stacked");
|
||||
}
|
||||
|
||||
/* Write dateAxis if date axis data is present. */
|
||||
if (sparkline->date_axis) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("dateAxis", "1");
|
||||
}
|
||||
|
||||
/* Write displayEmptyCellsAs. */
|
||||
if (sparkline->empty_cells == LXW_SPARKLINE_EMPTY_CELLS_ZERO) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("displayEmptyCellsAs", "zero");
|
||||
}
|
||||
else if (sparkline->empty_cells == LXW_SPARKLINE_EMPTY_CELLS_SPAN) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("displayEmptyCellsAs", "span");
|
||||
}
|
||||
|
||||
/* Write markers. */
|
||||
if (sparkline->markers) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("markers", "1");
|
||||
}
|
||||
|
||||
/* Write high. */
|
||||
if (sparkline->high_point) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("high", "1");
|
||||
}
|
||||
|
||||
/* Write low. */
|
||||
if (sparkline->low_point) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("low", "1");
|
||||
}
|
||||
|
||||
/* Write first. */
|
||||
if (sparkline->first_point) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("first", "1");
|
||||
}
|
||||
|
||||
/* Write last. */
|
||||
if (sparkline->last_point) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("last", "1");
|
||||
}
|
||||
|
||||
/* Write negative. */
|
||||
if (sparkline->negative_points) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("negative", "1");
|
||||
}
|
||||
|
||||
/* Write displayXAxis. */
|
||||
if (sparkline->show_axis) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("displayXAxis", "1");
|
||||
}
|
||||
|
||||
/* Write displayHidden. */
|
||||
if (sparkline->show_hidden) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("displayHidden", "1");
|
||||
}
|
||||
|
||||
/* Write minAxisType. */
|
||||
if (sparkline->min_axis_type == LXW_SPARKLINE_AXIS_GROUP) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("minAxisType", "group");
|
||||
}
|
||||
else if (sparkline->min_axis_type == LXW_SPARKLINE_AXIS_CUSTOM) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("minAxisType", "custom");
|
||||
}
|
||||
|
||||
/* Write maxAxisType. */
|
||||
if (sparkline->max_axis_type == LXW_SPARKLINE_AXIS_GROUP) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("maxAxisType", "group");
|
||||
}
|
||||
else if (sparkline->max_axis_type == LXW_SPARKLINE_AXIS_CUSTOM) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("maxAxisType", "custom");
|
||||
}
|
||||
|
||||
/* Write rightToLeft. */
|
||||
if (sparkline->reverse) {
|
||||
LXW_PUSH_ATTRIBUTES_STR("rightToLeft", "1");
|
||||
}
|
||||
|
||||
lxw_xml_start_tag(self->file, "x14:sparklineGroup", &attributes);
|
||||
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
|
||||
/* Write colors. */
|
||||
_worksheet_write_sparkline_color(self, "x14:colorSeries",
|
||||
sparkline->series_color);
|
||||
_worksheet_write_sparkline_color(self, "x14:colorNegative",
|
||||
sparkline->negative_color);
|
||||
|
||||
/* Write the colorAxis element (always black FF000000). */
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("rgb", "FF000000");
|
||||
lxw_xml_empty_tag(self->file, "x14:colorAxis", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
}
|
||||
|
||||
_worksheet_write_sparkline_color(self, "x14:colorMarkers",
|
||||
sparkline->markers_color);
|
||||
_worksheet_write_sparkline_color(self, "x14:colorFirst",
|
||||
sparkline->first_color);
|
||||
_worksheet_write_sparkline_color(self, "x14:colorLast",
|
||||
sparkline->last_color);
|
||||
_worksheet_write_sparkline_color(self, "x14:colorHigh",
|
||||
sparkline->high_color);
|
||||
_worksheet_write_sparkline_color(self, "x14:colorLow",
|
||||
sparkline->low_color);
|
||||
|
||||
/* Write date axis formula if present. */
|
||||
if (sparkline->date_axis) {
|
||||
lxw_xml_data_element(self->file, "xm:f", sparkline->date_axis, NULL);
|
||||
}
|
||||
|
||||
/* Write the sparklines container. */
|
||||
lxw_xml_start_tag(self->file, "x14:sparklines", NULL);
|
||||
|
||||
/* Write the sparkline element. */
|
||||
lxw_xml_start_tag(self->file, "x14:sparkline", NULL);
|
||||
lxw_xml_data_element(self->file, "xm:f", sparkline->range, NULL);
|
||||
lxw_xml_data_element(self->file, "xm:sqref", sparkline->location, NULL);
|
||||
lxw_xml_end_tag(self->file, "x14:sparkline");
|
||||
|
||||
lxw_xml_end_tag(self->file, "x14:sparklines");
|
||||
lxw_xml_end_tag(self->file, "x14:sparklineGroup");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <extLst> element for sparklines.
|
||||
*/
|
||||
STATIC void
|
||||
_worksheet_write_ext_list_sparklines(lxw_worksheet *self)
|
||||
{
|
||||
struct xml_attribute_list attributes;
|
||||
struct xml_attribute *attribute;
|
||||
lxw_sparkline *sparkline;
|
||||
char xmlns_xm[] = "http://schemas.microsoft.com/office/excel/2006/main";
|
||||
|
||||
_worksheet_write_ext(self, "{05C60535-1F16-4fd2-B633-F4F36F0B64E0}");
|
||||
|
||||
LXW_INIT_ATTRIBUTES();
|
||||
LXW_PUSH_ATTRIBUTES_STR("xmlns:xm", xmlns_xm);
|
||||
lxw_xml_start_tag(self->file, "x14:sparklineGroups", &attributes);
|
||||
LXW_FREE_ATTRIBUTES();
|
||||
|
||||
STAILQ_FOREACH(sparkline, self->sparklines, list_pointers) {
|
||||
_worksheet_write_sparkline_group(self, sparkline);
|
||||
}
|
||||
|
||||
lxw_xml_end_tag(self->file, "x14:sparklineGroups");
|
||||
lxw_xml_end_tag(self->file, "ext");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the <extLst> element for Excel 2010 conditional formatting data bars.
|
||||
*/
|
||||
|
|
@ -7187,12 +7507,16 @@ _worksheet_write_ext_list_data_bars(lxw_worksheet *self)
|
|||
STATIC void
|
||||
_worksheet_write_ext_list(lxw_worksheet *self)
|
||||
{
|
||||
if (self->data_bar_2010_index == 0)
|
||||
if (self->data_bar_2010_index == 0 && !self->has_sparklines)
|
||||
return;
|
||||
|
||||
lxw_xml_start_tag(self->file, "extLst", NULL);
|
||||
|
||||
_worksheet_write_ext_list_data_bars(self);
|
||||
if (self->data_bar_2010_index > 0)
|
||||
_worksheet_write_ext_list_data_bars(self);
|
||||
|
||||
if (self->has_sparklines)
|
||||
_worksheet_write_ext_list_sparklines(self);
|
||||
|
||||
lxw_xml_end_tag(self->file, "extLst");
|
||||
}
|
||||
|
|
@ -8317,6 +8641,31 @@ worksheet_write_boolean(lxw_worksheet *self,
|
|||
return LXW_NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a checkbox to a cell in Excel.
|
||||
*/
|
||||
lxw_error
|
||||
worksheet_insert_checkbox(lxw_worksheet *self,
|
||||
lxw_row_t row_num, lxw_col_t col_num,
|
||||
int value)
|
||||
{
|
||||
lxw_cell *cell;
|
||||
lxw_error err;
|
||||
|
||||
err = _check_dimensions(self, row_num, col_num, LXW_FALSE, LXW_FALSE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
cell = _new_boolean_cell(row_num, col_num, value ? 1 : 0,
|
||||
self->checkbox_format);
|
||||
|
||||
_insert_cell(self, row_num, col_num, cell);
|
||||
|
||||
self->has_checkboxes = LXW_TRUE;
|
||||
|
||||
return LXW_NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a date and or time to a cell in Excel.
|
||||
*/
|
||||
|
|
@ -8334,9 +8683,9 @@ worksheet_write_datetime(lxw_worksheet *self,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = lxw_datetime_validate(datetime);
|
||||
if (err)
|
||||
return err;
|
||||
printf("worksheet_write_datetime(): %d-%02d-%02d - 1904: %d\n",
|
||||
datetime->year, datetime->month, datetime->day,
|
||||
self->use_1904_epoch);
|
||||
|
||||
excel_date =
|
||||
lxw_datetime_to_excel_date_with_epoch(datetime, self->use_1904_epoch);
|
||||
|
|
@ -9556,6 +9905,103 @@ error:
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a sparkline to the worksheet.
|
||||
*/
|
||||
lxw_error
|
||||
worksheet_add_sparkline(lxw_worksheet *self, lxw_row_t row, lxw_col_t col,
|
||||
lxw_sparkline_options *user_options)
|
||||
{
|
||||
lxw_sparkline *sparkline;
|
||||
lxw_error err;
|
||||
char location[LXW_MAX_CELL_NAME_LENGTH];
|
||||
|
||||
if (!user_options) {
|
||||
LXW_WARN("worksheet_add_sparkline(): options parameter cannot be NULL");
|
||||
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
||||
}
|
||||
|
||||
if (!user_options->range || user_options->range[0] == '\0') {
|
||||
LXW_WARN("worksheet_add_sparkline(): range parameter is required");
|
||||
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
||||
}
|
||||
|
||||
/* Check that row and column are valid. */
|
||||
err = _check_dimensions(self, row, col, LXW_FALSE, LXW_FALSE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Create sparkline object. */
|
||||
sparkline = calloc(1, sizeof(lxw_sparkline));
|
||||
RETURN_ON_MEM_ERROR(sparkline, LXW_ERROR_MEMORY_MALLOC_FAILED);
|
||||
|
||||
/* Copy required range. */
|
||||
sparkline->range = lxw_strdup(user_options->range);
|
||||
if (!sparkline->range) {
|
||||
free(sparkline);
|
||||
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
||||
}
|
||||
|
||||
/* Set location from row/col. */
|
||||
lxw_rowcol_to_cell(location, row, col);
|
||||
sparkline->location = lxw_strdup(location);
|
||||
if (!sparkline->location) {
|
||||
free(sparkline->range);
|
||||
free(sparkline);
|
||||
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
||||
}
|
||||
|
||||
sparkline->row = row;
|
||||
sparkline->col = col;
|
||||
|
||||
/* Copy options. */
|
||||
sparkline->type = user_options->type;
|
||||
sparkline->style = user_options->style;
|
||||
sparkline->high_point = user_options->high_point;
|
||||
sparkline->low_point = user_options->low_point;
|
||||
sparkline->negative_points = user_options->negative_points;
|
||||
sparkline->first_point = user_options->first_point;
|
||||
sparkline->last_point = user_options->last_point;
|
||||
sparkline->markers = user_options->markers;
|
||||
|
||||
sparkline->series_color = user_options->series_color;
|
||||
sparkline->negative_color = user_options->negative_color;
|
||||
sparkline->markers_color = user_options->markers_color;
|
||||
sparkline->first_color = user_options->first_color;
|
||||
sparkline->last_color = user_options->last_color;
|
||||
sparkline->high_color = user_options->high_color;
|
||||
sparkline->low_color = user_options->low_color;
|
||||
|
||||
sparkline->min = user_options->min;
|
||||
sparkline->max = user_options->max;
|
||||
sparkline->min_axis_type = user_options->min_axis_type;
|
||||
sparkline->max_axis_type = user_options->max_axis_type;
|
||||
|
||||
sparkline->show_axis = user_options->show_axis;
|
||||
sparkline->reverse = user_options->reverse;
|
||||
sparkline->show_hidden = user_options->show_hidden;
|
||||
sparkline->empty_cells = user_options->empty_cells;
|
||||
|
||||
sparkline->weight = user_options->weight;
|
||||
if (sparkline->weight == 0.0)
|
||||
sparkline->weight = 0.75; /* Default line weight */
|
||||
|
||||
if (user_options->date_axis) {
|
||||
sparkline->date_axis = lxw_strdup(user_options->date_axis);
|
||||
if (!sparkline->date_axis) {
|
||||
free(sparkline->range);
|
||||
free(sparkline->location);
|
||||
free(sparkline);
|
||||
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
STAILQ_INSERT_TAIL(self->sparklines, sparkline, list_pointers);
|
||||
self->has_sparklines = LXW_TRUE;
|
||||
|
||||
return LXW_NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set this worksheet as a selected worksheet, i.e. the worksheet has its tab
|
||||
* highlighted.
|
||||
|
|
@ -9795,12 +10241,6 @@ worksheet_set_page_view(lxw_worksheet *self)
|
|||
void
|
||||
worksheet_set_paper(lxw_worksheet *self, uint8_t paper_size)
|
||||
{
|
||||
if (paper_size > 118) {
|
||||
LXW_WARN_FORMAT1("worksheet_set_paper(): invalid paper size: %d. "
|
||||
"Valid range is 0-118", paper_size);
|
||||
return;
|
||||
}
|
||||
|
||||
self->paper_size = paper_size;
|
||||
self->page_setup_changed = LXW_TRUE;
|
||||
}
|
||||
|
|
@ -11139,6 +11579,79 @@ worksheet_insert_chart(lxw_worksheet *self,
|
|||
return worksheet_insert_chart_opt(self, row_num, col_num, chart, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a textbox into the worksheet, with options.
|
||||
*/
|
||||
lxw_error
|
||||
worksheet_insert_textbox_opt(lxw_worksheet *self,
|
||||
lxw_row_t row_num, lxw_col_t col_num,
|
||||
const char *text,
|
||||
lxw_textbox_options *user_options)
|
||||
{
|
||||
lxw_object_properties *object_props;
|
||||
|
||||
if (!text) {
|
||||
LXW_WARN("worksheet_insert_textbox()/_opt(): "
|
||||
"text must be specified.");
|
||||
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
||||
}
|
||||
|
||||
/* Create a new object to hold the textbox properties. */
|
||||
object_props = calloc(1, sizeof(lxw_object_properties));
|
||||
RETURN_ON_MEM_ERROR(object_props, LXW_ERROR_MEMORY_MALLOC_FAILED);
|
||||
|
||||
if (user_options) {
|
||||
object_props->x_offset = user_options->x_offset;
|
||||
object_props->y_offset = user_options->y_offset;
|
||||
object_props->x_scale = user_options->x_scale;
|
||||
object_props->y_scale = user_options->y_scale;
|
||||
object_props->object_position = user_options->object_position;
|
||||
object_props->description = lxw_strdup(user_options->description);
|
||||
object_props->decorative = user_options->decorative;
|
||||
|
||||
if (user_options->width)
|
||||
object_props->width = user_options->width;
|
||||
if (user_options->height)
|
||||
object_props->height = user_options->height;
|
||||
}
|
||||
|
||||
/* Copy other options or set defaults. */
|
||||
object_props->row = row_num;
|
||||
object_props->col = col_num;
|
||||
object_props->text = lxw_strdup(text);
|
||||
object_props->is_textbox = LXW_TRUE;
|
||||
|
||||
/* Default textbox size is 192 x 120 pixels. */
|
||||
if (object_props->width == 0)
|
||||
object_props->width = 192;
|
||||
|
||||
if (object_props->height == 0)
|
||||
object_props->height = 120;
|
||||
|
||||
if (object_props->x_scale == 0.0)
|
||||
object_props->x_scale = 1;
|
||||
|
||||
if (object_props->y_scale == 0.0)
|
||||
object_props->y_scale = 1;
|
||||
|
||||
STAILQ_INSERT_TAIL(self->textbox_data, object_props, list_pointers);
|
||||
|
||||
self->has_textboxes = LXW_TRUE;
|
||||
|
||||
return LXW_NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a textbox into the worksheet.
|
||||
*/
|
||||
lxw_error
|
||||
worksheet_insert_textbox(lxw_worksheet *self,
|
||||
lxw_row_t row_num, lxw_col_t col_num,
|
||||
const char *text)
|
||||
{
|
||||
return worksheet_insert_textbox_opt(self, row_num, col_num, text, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a data validation to a worksheet, for a range. Ironically this requires
|
||||
* a lot of validation of the user input.
|
||||
|
|
|
|||
25
test/functional/src/test_autofit01.c
Normal file
25
test/functional/src/test_autofit01.c
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*****************************************************************************
|
||||
* Test cases for libxlsxwriter.
|
||||
*
|
||||
* Test to compare output against Excel files.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("test_autofit01.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
|
||||
/* Write a single character. */
|
||||
worksheet_write_string(worksheet, 0, 0, "A", NULL);
|
||||
|
||||
/* Set column width (simulating what autofit would do after user override). */
|
||||
worksheet_set_column(worksheet, 0, 0, 1.57143, NULL);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
worksheet_insert_chart(worksheet, CELL("E9"), chart);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
worksheet_insert_chart(worksheet, CELL("E9"), chart);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
worksheet_insert_chart(worksheet, CELL("E9"), chart);
|
||||
|
||||
|
|
|
|||
40
test/functional/src/test_chart_area04.c
Normal file
40
test/functional/src/test_chart_area04.c
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*****************************************************************************
|
||||
* Test cases for libxlsxwriter.
|
||||
*
|
||||
* Test to compare output against Excel files.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
* Copyright 2014-2025, John McNamara, jmcnamara@cpan.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xlsxwriter.h"
|
||||
|
||||
int main() {
|
||||
|
||||
lxw_workbook *workbook = workbook_new("test_chart_area04.xlsx");
|
||||
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
|
||||
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_AREA);
|
||||
|
||||
/* For testing, copy the randomly generated axis ids in the target file. */
|
||||
chart->axis_id_1 = 63591168;
|
||||
chart->axis_id_2 = 63592704;
|
||||
chart->axis_id_3 = 74921856;
|
||||
chart->axis_id_4 = 73764224;
|
||||
|
||||
uint8_t data1[5] = {1, 2, 3, 4, 5};
|
||||
uint8_t data2[5] = {6, 8, 6, 4, 2};
|
||||
|
||||
int row;
|
||||
for (row = 0; row < 5; row++) {
|
||||
worksheet_write_number(worksheet, row, 0, data1[row], NULL);
|
||||
worksheet_write_number(worksheet, row, 1, data2[row], NULL);
|
||||
}
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 1);
|
||||
|
||||
worksheet_insert_chart(worksheet, CELL("E9"), chart);
|
||||
|
||||
return workbook_close(workbook);
|
||||
}
|
||||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
lxw_chart_options chart_options = {.description = "Some alternative text"};
|
||||
worksheet_insert_chart_opt(worksheet, CELL("E9"), chart, &chart_options);
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
lxw_chart_options chart_options = {.description = "Some alternative text", .decorative = LXW_TRUE};
|
||||
worksheet_insert_chart_opt(worksheet, CELL("E9"), chart, &chart_options);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_name(chart->x_axis, "XXX");
|
||||
chart_axis_set_name(chart->y_axis, "YYY");
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_name(chart->x_axis, "XXX");
|
||||
chart_axis_set_name(chart->y_axis, "YYY");
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_axis_set_name(chart->x_axis, "XXX");
|
||||
chart_axis_set_name(chart->y_axis, "YYY");
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_name(chart->x_axis, "XXX");
|
||||
chart_axis_set_name(chart->y_axis, "YYY");
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$3",
|
||||
"=Sheet1!$B$1:$B$3"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_title_set_name(chart, "Title");
|
||||
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_axis_set_name(chart->x_axis, "XXX");
|
||||
chart_axis_set_name(chart->y_axis, "YYY");
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_axis_set_reverse(chart->y_axis);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_reverse(chart->x_axis);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_axis_set_reverse(chart->x_axis);
|
||||
chart_axis_set_reverse(chart->y_axis);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_min(chart->x_axis, 0);
|
||||
chart_axis_set_max(chart->x_axis, 20);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_min(chart->y_axis, 0);
|
||||
chart_axis_set_max(chart->y_axis, 16);
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_axis_set_min(chart->x_axis, 0);
|
||||
chart_axis_set_max(chart->x_axis, 6);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_major_unit(chart->y_axis, 2);
|
||||
chart_axis_set_minor_unit(chart->y_axis, 0.4);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_log_base(chart->y_axis, 10);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_series_set_invert_if_negative(series);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_label_position(chart->x_axis, LXW_CHART_AXIS_LABEL_POSITION_HIGH);
|
||||
chart_axis_set_label_position(chart->y_axis, LXW_CHART_AXIS_LABEL_POSITION_LOW);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_label_position(chart->x_axis, LXW_CHART_AXIS_LABEL_POSITION_NEXT_TO);
|
||||
chart_axis_set_label_position(chart->y_axis, LXW_CHART_AXIS_LABEL_POSITION_NONE);
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ int main() {
|
|||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$B$1:$B$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_add_series(chart,
|
||||
"=Sheet1!$A$1:$A$5",
|
||||
"=Sheet1!$C$1:$C$5"
|
||||
);
|
||||
, 0);
|
||||
|
||||
chart_axis_set_reverse(chart->x_axis);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_num_format(chart->x_axis, "#,##0.00");
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_num_format(chart->x_axis, "dd/mm/yyyy");
|
||||
chart_axis_set_num_format(chart->y_axis, "0.00%");
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_num_format(chart->x_axis, "dd/mm/yyyy");
|
||||
chart_axis_set_num_format(chart->y_axis, "0.00%");
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_num_format(chart->x_axis, "[$¥-411]#,##0.00");
|
||||
chart_axis_set_num_format(chart->y_axis, "0.00%");
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
lxw_chart_font font1 = {.rotation = 45, .baseline = -1};
|
||||
chart_axis_set_num_font(chart->x_axis, &font1);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
lxw_chart_font font1 = {.rotation = -35, .baseline = -1};
|
||||
chart_axis_set_num_font(chart->x_axis, &font1);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
lxw_chart_font font1 = {.rotation = 90, .baseline = -1};
|
||||
chart_axis_set_num_font(chart->x_axis, &font1);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
lxw_chart_font font1 = {.rotation = -90, .baseline = -1};
|
||||
chart_axis_set_num_font(chart->x_axis, &font1);
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ int main() {
|
|||
|
||||
chart_axis_set_position(chart->x_axis, LXW_CHART_AXIS_POSITION_ON_TICK);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
worksheet_insert_chart(worksheet, CELL("E9"), chart);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ int main() {
|
|||
|
||||
chart_axis_set_position(chart->y_axis, LXW_CHART_AXIS_POSITION_ON_TICK);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
worksheet_insert_chart(worksheet, CELL("E9"), chart);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ int main() {
|
|||
|
||||
chart_axis_set_position(chart->x_axis, LXW_CHART_AXIS_POSITION_BETWEEN);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
worksheet_insert_chart(worksheet, CELL("E9"), chart);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
lxw_chart_font font1 = {.rotation = -45, .baseline = -1};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ int main() {
|
|||
for (col = 0; col < 3; col++)
|
||||
worksheet_write_number(worksheet, row, col, data[row][col], NULL);
|
||||
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
|
||||
chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0);
|
||||
chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0);
|
||||
|
||||
chart_axis_set_interval_unit(chart->x_axis, 2);
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue