From fc0c7bd38283a25ff86c444f87d16aa807e0f950 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 2 Jan 2026 22:30:12 -0600 Subject: [PATCH 1/2] - 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. --- .indent.pro | 1 + Changes.txt | 82 +- build.zig | 97 +- build.zig.zon | 2 +- dev/fuzzing/build.sh | 2 +- docs/WINDOWS_BUILD.md | 368 ++++ docs/src/working_with_charts.dox | 12 +- examples/chart.c | 6 +- examples/chart_area.c | 12 +- examples/chart_bar.c | 12 +- examples/chart_clustered.c | 6 +- examples/chart_column.c | 12 +- examples/chart_combined.c | 146 ++ examples/chart_data_labels.c | 18 +- examples/chart_data_table.c | 8 +- examples/chart_data_tools.c | 28 +- examples/chart_doughnut.c | 8 +- examples/chart_fonts.c | 2 +- examples/chart_gauge.c | 105 ++ examples/chart_gradient.c | 97 ++ examples/chart_line.c | 12 +- examples/chart_pareto.c | 102 ++ examples/chart_pattern.c | 4 +- examples/chart_pie.c | 6 +- examples/chart_pie_colors.c | 2 +- examples/chart_radar.c | 12 +- examples/chart_scatter.c | 20 +- examples/chart_secondary_axis.c | 84 + examples/chart_stock.c | 66 + examples/chart_styles.c | 2 +- examples/chart_working_with_example.c | 2 +- examples/chartsheet.c | 4 +- examples/checkbox.c | 32 + examples/colors.c | 77 + examples/right_to_left.c | 57 + examples/sparklines.c | 86 + examples/text_indent.c | 32 + examples/textbox.c | 30 + include/xlsxwriter.h | 6 +- include/xlsxwriter/chart.h | 346 +++- include/xlsxwriter/common.h | 3 - include/xlsxwriter/content_types.h | 1 + include/xlsxwriter/drawing.h | 37 + include/xlsxwriter/feature_property_bag.h | 58 + include/xlsxwriter/format.h | 22 + include/xlsxwriter/packager.h | 1 + include/xlsxwriter/relationships.h | 1 + include/xlsxwriter/sparkline.h | 205 +++ include/xlsxwriter/utility.h | 65 +- include/xlsxwriter/workbook.h | 3 + include/xlsxwriter/worksheet.h | 140 ++ src/chart.c | 1479 +++++++++++++++-- src/content_types.c | 11 + src/drawing.c | 327 +++- src/feature_property_bag.c | 259 +++ src/format.c | 30 +- src/labview_wrappers.c | 703 ++++++++ src/packager.c | 51 + src/relationships.c | 12 + src/styles.c | 34 +- src/utility.c | 224 ++- src/workbook.c | 59 +- src/worksheet.c | 544 +++++- test/functional/src/test_autofit01.c | 25 + test/functional/src/test_chart_area01.c | 4 +- test/functional/src/test_chart_area02.c | 4 +- test/functional/src/test_chart_area03.c | 4 +- test/functional/src/test_chart_area04.c | 40 + test/functional/src/test_chart_area05.c | 4 +- test/functional/src/test_chart_area06.c | 4 +- test/functional/src/test_chart_axis01.c | 6 +- test/functional/src/test_chart_axis02.c | 6 +- test/functional/src/test_chart_axis04.c | 4 +- test/functional/src/test_chart_axis05.c | 6 +- test/functional/src/test_chart_axis06.c | 2 +- test/functional/src/test_chart_axis07.c | 4 +- test/functional/src/test_chart_axis08.c | 4 +- test/functional/src/test_chart_axis09.c | 6 +- test/functional/src/test_chart_axis10.c | 4 +- test/functional/src/test_chart_axis11.c | 6 +- test/functional/src/test_chart_axis12.c | 6 +- test/functional/src/test_chart_axis13.c | 4 +- test/functional/src/test_chart_axis15.c | 6 +- test/functional/src/test_chart_axis17.c | 6 +- test/functional/src/test_chart_axis18.c | 6 +- test/functional/src/test_chart_axis19.c | 6 +- test/functional/src/test_chart_axis20.c | 6 +- test/functional/src/test_chart_axis21.c | 4 +- test/functional/src/test_chart_axis22.c | 6 +- test/functional/src/test_chart_axis23.c | 6 +- test/functional/src/test_chart_axis24.c | 6 +- test/functional/src/test_chart_axis25.c | 6 +- test/functional/src/test_chart_axis26.c | 6 +- test/functional/src/test_chart_axis27.c | 6 +- test/functional/src/test_chart_axis28.c | 6 +- test/functional/src/test_chart_axis29.c | 6 +- test/functional/src/test_chart_axis30.c | 6 +- test/functional/src/test_chart_axis31.c | 6 +- test/functional/src/test_chart_axis32.c | 6 +- test/functional/src/test_chart_axis33.c | 6 +- test/functional/src/test_chart_axis34.c | 6 +- test/functional/src/test_chart_axis35.c | 6 +- test/functional/src/test_chart_axis36.c | 6 +- test/functional/src/test_chart_axis37.c | 6 +- test/functional/src/test_chart_axis38.c | 6 +- test/functional/src/test_chart_axis39.c | 4 +- test/functional/src/test_chart_axis40.c | 6 +- test/functional/src/test_chart_axis41.c | 6 +- test/functional/src/test_chart_axis42.c | 6 +- test/functional/src/test_chart_axis43.c | 6 +- test/functional/src/test_chart_axis44.c | 6 +- test/functional/src/test_chart_axis45.c | 6 +- test/functional/src/test_chart_axis46.c | 6 +- test/functional/src/test_chart_axis47.c | 6 +- test/functional/src/test_chart_axis48.c | 6 +- test/functional/src/test_chart_bar01.c | 4 +- test/functional/src/test_chart_bar02.c | 4 +- test/functional/src/test_chart_bar03.c | 8 +- test/functional/src/test_chart_bar04.c | 8 +- test/functional/src/test_chart_bar05.c | 6 +- test/functional/src/test_chart_bar06.c | 6 +- test/functional/src/test_chart_bar08.c | 6 +- test/functional/src/test_chart_bar09.c | 6 +- test/functional/src/test_chart_bar10.c | 6 +- test/functional/src/test_chart_bar11.c | 12 +- test/functional/src/test_chart_bar12.c | 6 +- test/functional/src/test_chart_bar13.c | 12 +- test/functional/src/test_chart_bar14.c | 14 +- test/functional/src/test_chart_bar15.c | 8 +- test/functional/src/test_chart_bar16.c | 6 +- test/functional/src/test_chart_bar17.c | 6 +- test/functional/src/test_chart_bar18.c | 6 +- test/functional/src/test_chart_bar19.c | 6 +- test/functional/src/test_chart_bar20.c | 6 +- test/functional/src/test_chart_bar21.c | 4 +- test/functional/src/test_chart_bar22.c | 6 +- test/functional/src/test_chart_bar24.c | 40 + test/functional/src/test_chart_bar51.c | 4 +- test/functional/src/test_chart_bar52.c | 4 +- test/functional/src/test_chart_bar53.c | 8 +- test/functional/src/test_chart_bar54.c | 8 +- test/functional/src/test_chart_bar55.c | 6 +- test/functional/src/test_chart_bar61.c | 4 +- test/functional/src/test_chart_bar65.c | 6 +- test/functional/src/test_chart_bar69.c | 6 +- test/functional/src/test_chart_bar70.c | 6 +- test/functional/src/test_chart_blank01.c | 6 +- test/functional/src/test_chart_blank02.c | 6 +- test/functional/src/test_chart_blank03.c | 6 +- test/functional/src/test_chart_blank04.c | 6 +- test/functional/src/test_chart_blank05.c | 6 +- test/functional/src/test_chart_blank06.c | 6 +- test/functional/src/test_chart_chartarea01.c | 6 +- test/functional/src/test_chart_chartarea03.c | 4 +- test/functional/src/test_chart_chartarea05.c | 2 +- test/functional/src/test_chart_chartarea06.c | 2 +- test/functional/src/test_chart_clustered01.c | 78 + test/functional/src/test_chart_column01.c | 6 +- test/functional/src/test_chart_column02.c | 6 +- test/functional/src/test_chart_column03.c | 6 +- test/functional/src/test_chart_column04.c | 40 + test/functional/src/test_chart_column05.c | 6 +- test/functional/src/test_chart_column06.c | 6 +- test/functional/src/test_chart_column07.c | 2 +- test/functional/src/test_chart_column08.c | 2 +- test/functional/src/test_chart_column09.c | 2 +- test/functional/src/test_chart_column10.c | 2 +- test/functional/src/test_chart_column11.c | 6 +- test/functional/src/test_chart_column12.c | 6 +- test/functional/src/test_chart_column13.c | 2 +- test/functional/src/test_chart_combined01.c | 38 + test/functional/src/test_chart_combined02.c | 41 + test/functional/src/test_chart_combined03.c | 41 + test/functional/src/test_chart_combined04.c | 50 + test/functional/src/test_chart_combined05.c | 47 + test/functional/src/test_chart_combined06.c | 44 + test/functional/src/test_chart_combined07.c | 44 + test/functional/src/test_chart_combined08.c | 49 + test/functional/src/test_chart_combined09.c | 53 + test/functional/src/test_chart_combined10.c | 44 + test/functional/src/test_chart_combined11.c | 76 + test/functional/src/test_chart_crossing01.c | 6 +- test/functional/src/test_chart_crossing02.c | 6 +- test/functional/src/test_chart_crossing03.c | 4 +- test/functional/src/test_chart_crossing04.c | 4 +- test/functional/src/test_chart_crossing05.c | 6 +- test/functional/src/test_chart_crossing06.c | 6 +- .../functional/src/test_chart_data_labels01.c | 6 +- .../functional/src/test_chart_data_labels02.c | 6 +- .../functional/src/test_chart_data_labels03.c | 6 +- .../functional/src/test_chart_data_labels04.c | 6 +- .../functional/src/test_chart_data_labels05.c | 6 +- .../functional/src/test_chart_data_labels06.c | 6 +- .../functional/src/test_chart_data_labels07.c | 2 +- .../functional/src/test_chart_data_labels08.c | 4 +- .../functional/src/test_chart_data_labels09.c | 4 +- .../functional/src/test_chart_data_labels10.c | 4 +- .../functional/src/test_chart_data_labels11.c | 2 +- .../functional/src/test_chart_data_labels12.c | 2 +- .../functional/src/test_chart_data_labels13.c | 2 +- .../functional/src/test_chart_data_labels14.c | 2 +- .../functional/src/test_chart_data_labels15.c | 2 +- .../functional/src/test_chart_data_labels16.c | 2 +- .../functional/src/test_chart_data_labels18.c | 6 +- .../functional/src/test_chart_data_labels19.c | 6 +- .../functional/src/test_chart_data_labels20.c | 6 +- .../functional/src/test_chart_data_labels21.c | 2 +- .../functional/src/test_chart_data_labels22.c | 6 +- .../functional/src/test_chart_data_labels23.c | 6 +- .../functional/src/test_chart_data_labels24.c | 6 +- .../functional/src/test_chart_data_labels25.c | 6 +- .../functional/src/test_chart_data_labels26.c | 6 +- .../functional/src/test_chart_data_labels27.c | 6 +- .../functional/src/test_chart_data_labels28.c | 6 +- .../functional/src/test_chart_data_labels29.c | 6 +- .../functional/src/test_chart_data_labels30.c | 6 +- .../functional/src/test_chart_data_labels31.c | 6 +- .../functional/src/test_chart_data_labels32.c | 6 +- .../functional/src/test_chart_data_labels33.c | 6 +- .../functional/src/test_chart_data_labels34.c | 6 +- .../functional/src/test_chart_data_labels35.c | 6 +- .../functional/src/test_chart_data_labels36.c | 2 +- .../functional/src/test_chart_data_labels37.c | 6 +- .../functional/src/test_chart_data_labels38.c | 6 +- .../functional/src/test_chart_data_labels40.c | 6 +- .../functional/src/test_chart_data_labels41.c | 6 +- .../functional/src/test_chart_data_labels42.c | 6 +- .../functional/src/test_chart_data_labels43.c | 6 +- .../functional/src/test_chart_data_labels44.c | 6 +- .../functional/src/test_chart_data_labels45.c | 6 +- .../functional/src/test_chart_data_labels46.c | 6 +- .../functional/src/test_chart_data_labels47.c | 6 +- .../functional/src/test_chart_data_labels48.c | 6 +- .../functional/src/test_chart_data_labels49.c | 6 +- .../functional/src/test_chart_data_labels50.c | 6 +- test/functional/src/test_chart_date01.c | 62 + .../src/test_chart_display_units01.c | 2 +- .../src/test_chart_display_units02.c | 2 +- .../src/test_chart_display_units03.c | 2 +- .../src/test_chart_display_units04.c | 2 +- .../src/test_chart_display_units05.c | 2 +- .../src/test_chart_display_units06.c | 2 +- .../src/test_chart_display_units07.c | 2 +- .../src/test_chart_display_units08.c | 2 +- .../src/test_chart_display_units09.c | 2 +- .../src/test_chart_display_units10.c | 2 +- .../src/test_chart_display_units11.c | 2 +- .../src/test_chart_display_units12.c | 2 +- test/functional/src/test_chart_doughnut01.c | 2 +- test/functional/src/test_chart_doughnut02.c | 2 +- test/functional/src/test_chart_doughnut03.c | 2 +- test/functional/src/test_chart_doughnut04.c | 2 +- test/functional/src/test_chart_doughnut05.c | 2 +- test/functional/src/test_chart_doughnut06.c | 4 +- test/functional/src/test_chart_drop_lines01.c | 4 +- test/functional/src/test_chart_drop_lines02.c | 4 +- test/functional/src/test_chart_drop_lines03.c | 4 +- test/functional/src/test_chart_errorbars01.c | 4 +- test/functional/src/test_chart_errorbars02.c | 4 +- test/functional/src/test_chart_errorbars03.c | 4 +- test/functional/src/test_chart_errorbars04.c | 4 +- test/functional/src/test_chart_errorbars05.c | 4 +- test/functional/src/test_chart_errorbars06.c | 4 +- test/functional/src/test_chart_font01.c | 6 +- test/functional/src/test_chart_font02.c | 6 +- test/functional/src/test_chart_font03.c | 6 +- test/functional/src/test_chart_font04.c | 6 +- test/functional/src/test_chart_font05.c | 6 +- test/functional/src/test_chart_font06.c | 6 +- test/functional/src/test_chart_font07.c | 6 +- test/functional/src/test_chart_font08.c | 6 +- test/functional/src/test_chart_font09.c | 6 +- test/functional/src/test_chart_format01.c | 4 +- test/functional/src/test_chart_format02.c | 4 +- test/functional/src/test_chart_format03.c | 4 +- test/functional/src/test_chart_format04.c | 4 +- test/functional/src/test_chart_format05.c | 4 +- test/functional/src/test_chart_format06.c | 4 +- test/functional/src/test_chart_format07.c | 4 +- test/functional/src/test_chart_format08.c | 4 +- test/functional/src/test_chart_format09.c | 4 +- test/functional/src/test_chart_format10.c | 4 +- test/functional/src/test_chart_format11.c | 4 +- test/functional/src/test_chart_format12.c | 4 +- test/functional/src/test_chart_format13.c | 4 +- test/functional/src/test_chart_format14.c | 4 +- test/functional/src/test_chart_format15.c | 4 +- test/functional/src/test_chart_format16.c | 4 +- test/functional/src/test_chart_format17.c | 6 +- test/functional/src/test_chart_format18.c | 6 +- test/functional/src/test_chart_format19.c | 6 +- test/functional/src/test_chart_format20.c | 8 +- test/functional/src/test_chart_format21.c | 4 +- test/functional/src/test_chart_format22.c | 4 +- test/functional/src/test_chart_format23.c | 4 +- test/functional/src/test_chart_format24.c | 4 +- test/functional/src/test_chart_format25.c | 4 +- test/functional/src/test_chart_format26.c | 4 +- test/functional/src/test_chart_format27.c | 4 +- test/functional/src/test_chart_format28.c | 4 +- test/functional/src/test_chart_format29.c | 4 +- test/functional/src/test_chart_format30.c | 4 +- test/functional/src/test_chart_format31.c | 4 +- test/functional/src/test_chart_format32.c | 4 +- test/functional/src/test_chart_gap01.c | 4 +- test/functional/src/test_chart_gap02.c | 4 +- test/functional/src/test_chart_gap03.c | 4 +- test/functional/src/test_chart_gap04.c | 48 + test/functional/src/test_chart_gap05.c | 51 + test/functional/src/test_chart_gradient01.c | 50 + test/functional/src/test_chart_gradient02.c | 51 + test/functional/src/test_chart_gradient03.c | 51 + test/functional/src/test_chart_gradient04.c | 51 + test/functional/src/test_chart_gradient05.c | 51 + test/functional/src/test_chart_gradient06.c | 51 + test/functional/src/test_chart_gradient07.c | 51 + test/functional/src/test_chart_gradient08.c | 50 + test/functional/src/test_chart_gradient09.c | 50 + test/functional/src/test_chart_gradient10.c | 50 + test/functional/src/test_chart_gradient11.c | 50 + test/functional/src/test_chart_gradient12.c | 51 + test/functional/src/test_chart_gradient13.c | 51 + test/functional/src/test_chart_gridlines01.c | 6 +- test/functional/src/test_chart_gridlines02.c | 4 +- test/functional/src/test_chart_gridlines04.c | 6 +- test/functional/src/test_chart_gridlines05.c | 6 +- test/functional/src/test_chart_gridlines06.c | 4 +- test/functional/src/test_chart_gridlines08.c | 6 +- test/functional/src/test_chart_gridlines09.c | 6 +- .../src/test_chart_high_low_lines01.c | 4 +- .../src/test_chart_high_low_lines02.c | 4 +- test/functional/src/test_chart_layout01.c | 6 +- test/functional/src/test_chart_layout02.c | 6 +- test/functional/src/test_chart_layout03.c | 6 +- test/functional/src/test_chart_layout04.c | 6 +- test/functional/src/test_chart_layout05.c | 4 +- test/functional/src/test_chart_layout06.c | 6 +- test/functional/src/test_chart_layout07.c | 6 +- test/functional/src/test_chart_layout08.c | 6 +- test/functional/src/test_chart_legend01.c | 6 +- test/functional/src/test_chart_legend03.c | 6 +- test/functional/src/test_chart_legend04.c | 6 +- test/functional/src/test_chart_line01.c | 6 +- test/functional/src/test_chart_line02.c | 40 + test/functional/src/test_chart_line03.c | 6 +- test/functional/src/test_chart_line04.c | 6 +- test/functional/src/test_chart_line05.c | 6 +- test/functional/src/test_chart_line06.c | 6 +- test/functional/src/test_chart_line07.c | 58 + test/functional/src/test_chart_line08.c | 63 + test/functional/src/test_chart_order01.c | 8 +- test/functional/src/test_chart_order02.c | 8 +- test/functional/src/test_chart_pattern01.c | 16 +- test/functional/src/test_chart_pattern02.c | 16 +- test/functional/src/test_chart_pattern03.c | 16 +- test/functional/src/test_chart_pattern04.c | 16 +- test/functional/src/test_chart_pattern05.c | 16 +- test/functional/src/test_chart_pattern06.c | 16 +- test/functional/src/test_chart_pattern07.c | 16 +- test/functional/src/test_chart_pattern08.c | 16 +- test/functional/src/test_chart_pattern10.c | 16 +- test/functional/src/test_chart_pie01.c | 2 +- test/functional/src/test_chart_pie02.c | 2 +- test/functional/src/test_chart_pie03.c | 2 +- test/functional/src/test_chart_pie04.c | 2 +- test/functional/src/test_chart_pie05.c | 2 +- test/functional/src/test_chart_points01.c | 2 +- test/functional/src/test_chart_points02.c | 2 +- test/functional/src/test_chart_points03.c | 2 +- test/functional/src/test_chart_points04.c | 4 +- test/functional/src/test_chart_points05.c | 4 +- test/functional/src/test_chart_points06.c | 4 +- test/functional/src/test_chart_radar01.c | 6 +- test/functional/src/test_chart_radar02.c | 6 +- test/functional/src/test_chart_radar03.c | 6 +- test/functional/src/test_chart_scatter01.c | 4 +- test/functional/src/test_chart_scatter02.c | 4 +- test/functional/src/test_chart_scatter03.c | 4 +- test/functional/src/test_chart_scatter04.c | 4 +- test/functional/src/test_chart_scatter05.c | 4 +- test/functional/src/test_chart_scatter06.c | 4 +- test/functional/src/test_chart_scatter07.c | 44 + test/functional/src/test_chart_scatter09.c | 4 +- test/functional/src/test_chart_scatter10.c | 4 +- test/functional/src/test_chart_scatter11.c | 4 +- test/functional/src/test_chart_scatter12.c | 4 +- test/functional/src/test_chart_scatter13.c | 4 +- test/functional/src/test_chart_scatter14.c | 4 +- test/functional/src/test_chart_scatter15.c | 2 +- test/functional/src/test_chart_size01.c | 6 +- test/functional/src/test_chart_size04.c | 6 +- test/functional/src/test_chart_sparse01.c | 4 +- test/functional/src/test_chart_stock01.c | 52 + test/functional/src/test_chart_stock02.c | 54 + test/functional/src/test_chart_stock03.c | 74 + test/functional/src/test_chart_str01.c | 6 +- test/functional/src/test_chart_str02.c | 4 +- test/functional/src/test_chart_table01.c | 6 +- test/functional/src/test_chart_table02.c | 6 +- test/functional/src/test_chart_table03.c | 6 +- test/functional/src/test_chart_title01.c | 2 +- test/functional/src/test_chart_title02.c | 2 +- test/functional/src/test_chart_title03.c | 2 +- .../src/test_chart_up_down_bars01.c | 4 +- .../src/test_chart_up_down_bars02.c | 4 +- test/functional/src/test_chartsheet01.c | 6 +- test/functional/src/test_chartsheet02.c | 6 +- test/functional/src/test_chartsheet03.c | 6 +- test/functional/src/test_chartsheet04.c | 6 +- test/functional/src/test_chartsheet05.c | 6 +- test/functional/src/test_chartsheet06.c | 6 +- test/functional/src/test_chartsheet07.c | 6 +- test/functional/src/test_chartsheet08.c | 6 +- test/functional/src/test_chartsheet09.c | 6 +- test/functional/src/test_checkbox01.c | 25 + test/functional/src/test_hyperlink36.c | 2 +- test/functional/src/test_object_position04.c | 6 +- test/functional/src/test_object_position08.c | 6 +- test/functional/src/test_object_position09.c | 6 +- test/functional/src/test_quote_name01.c | 2 +- test/functional/src/test_quote_name02.c | 2 +- test/functional/src/test_quote_name03.c | 2 +- test/functional/src/test_quote_name04.c | 2 +- test/functional/src/test_quote_name05.c | 6 +- test/functional/src/test_quote_name06.c | 6 +- test/functional/src/test_quote_name07.c | 6 +- test/functional/src/test_set_column05.c | 6 +- test/functional/src/test_set_column06.c | 6 +- test/functional/src/test_set_column11.c | 6 +- test/functional/src/test_sparkline01.c | 33 + test/functional/src/test_sparkline02.c | 36 + test/functional/src/test_sparkline03.c | 35 + test/functional/src/test_textbox01.c | 21 + test/functional/test_autofit.py | 19 + test/functional/test_chart_area.py | 5 + test/functional/test_chart_bar.py | 5 + test/functional/test_chart_column.py | 5 + test/functional/test_chart_combined.py | 58 + test/functional/test_chart_date.py | 26 + test/functional/test_chart_gap.py | 8 + test/functional/test_chart_line.py | 12 + test/functional/test_chart_scatter.py | 13 + test/functional/test_chart_stock.py | 35 + test/functional/test_checkbox.py | 19 + test/functional/test_sparkline.py | 25 + test/functional/test_textbox.py | 19 + test/functional/xlsx_files/autofit01.xlsx | Bin 0 -> 7358 bytes test/functional/xlsx_files/autofit02.xlsx | Bin 0 -> 7367 bytes test/functional/xlsx_files/autofit03.xlsx | Bin 0 -> 7388 bytes test/functional/xlsx_files/autofit04.xlsx | Bin 0 -> 7449 bytes test/functional/xlsx_files/autofit05.xlsx | Bin 0 -> 7104 bytes test/functional/xlsx_files/autofit06.xlsx | Bin 0 -> 7088 bytes test/functional/xlsx_files/autofit07.xlsx | Bin 0 -> 7876 bytes test/functional/xlsx_files/autofit08.xlsx | Bin 0 -> 7410 bytes test/functional/xlsx_files/autofit09.xlsx | Bin 0 -> 7478 bytes test/functional/xlsx_files/autofit10.xlsx | Bin 0 -> 7520 bytes test/functional/xlsx_files/autofit11.xlsx | Bin 0 -> 7345 bytes test/functional/xlsx_files/autofit12.xlsx | Bin 0 -> 7466 bytes test/functional/xlsx_files/autofit13.xlsx | Bin 0 -> 7510 bytes test/functional/xlsx_files/autofit14.xlsx | Bin 0 -> 5858 bytes test/functional/xlsx_files/chart_area04.xlsx | Bin 0 -> 9274 bytes test/functional/xlsx_files/chart_bar24.xlsx | Bin 0 -> 9306 bytes .../xlsx_files/chart_clustered01.xlsx | Bin 0 -> 9911 bytes .../functional/xlsx_files/chart_column04.xlsx | Bin 0 -> 9282 bytes .../xlsx_files/chart_combined01.xlsx | Bin 0 -> 9198 bytes .../xlsx_files/chart_combined02.xlsx | Bin 0 -> 7764 bytes .../xlsx_files/chart_combined03.xlsx | Bin 0 -> 7801 bytes .../xlsx_files/chart_combined04.xlsx | Bin 0 -> 7812 bytes .../xlsx_files/chart_combined05.xlsx | Bin 0 -> 9320 bytes .../xlsx_files/chart_combined06.xlsx | Bin 0 -> 9212 bytes .../xlsx_files/chart_combined07.xlsx | Bin 0 -> 9360 bytes .../xlsx_files/chart_combined08.xlsx | Bin 0 -> 9437 bytes .../xlsx_files/chart_combined09.xlsx | Bin 0 -> 9392 bytes .../xlsx_files/chart_combined10.xlsx | Bin 0 -> 9450 bytes .../xlsx_files/chart_combined11.xlsx | Bin 0 -> 9491 bytes test/functional/xlsx_files/chart_date01.xlsx | Bin 0 -> 9435 bytes test/functional/xlsx_files/chart_date02.xlsx | Bin 0 -> 9456 bytes test/functional/xlsx_files/chart_date03.xlsx | Bin 0 -> 9458 bytes test/functional/xlsx_files/chart_date04.xlsx | Bin 0 -> 9462 bytes test/functional/xlsx_files/chart_date05.xlsx | Bin 0 -> 9443 bytes test/functional/xlsx_files/chart_gap04.xlsx | Bin 0 -> 9316 bytes test/functional/xlsx_files/chart_gap05.xlsx | Bin 0 -> 9312 bytes .../xlsx_files/chart_gradient01.xlsx | Bin 0 -> 9365 bytes .../xlsx_files/chart_gradient02.xlsx | Bin 0 -> 9383 bytes .../xlsx_files/chart_gradient03.xlsx | Bin 0 -> 9384 bytes .../xlsx_files/chart_gradient04.xlsx | Bin 0 -> 9436 bytes .../xlsx_files/chart_gradient05.xlsx | Bin 0 -> 9434 bytes .../xlsx_files/chart_gradient06.xlsx | Bin 0 -> 9431 bytes .../xlsx_files/chart_gradient07.xlsx | Bin 0 -> 9405 bytes .../xlsx_files/chart_gradient08.xlsx | Bin 0 -> 9387 bytes .../xlsx_files/chart_gradient09.xlsx | Bin 0 -> 9388 bytes .../xlsx_files/chart_gradient10.xlsx | Bin 0 -> 9373 bytes .../xlsx_files/chart_gradient11.xlsx | Bin 0 -> 9393 bytes .../xlsx_files/chart_gradient12.xlsx | Bin 0 -> 9374 bytes .../xlsx_files/chart_gradient13.xlsx | Bin 0 -> 9389 bytes test/functional/xlsx_files/chart_line02.xlsx | Bin 0 -> 9295 bytes test/functional/xlsx_files/chart_line07.xlsx | Bin 0 -> 9447 bytes test/functional/xlsx_files/chart_line08.xlsx | Bin 0 -> 9446 bytes .../xlsx_files/chart_scatter07.xlsx | Bin 0 -> 9400 bytes test/functional/xlsx_files/chart_stock01.xlsx | Bin 0 -> 9586 bytes test/functional/xlsx_files/chart_stock02.xlsx | Bin 0 -> 9723 bytes test/functional/xlsx_files/chart_stock03.xlsx | Bin 0 -> 9650 bytes test/functional/xlsx_files/checkbox01.xlsx | Bin 0 -> 5589 bytes test/functional/xlsx_files/sparkline01.xlsx | Bin 0 -> 5147 bytes test/functional/xlsx_files/sparkline02.xlsx | Bin 0 -> 5166 bytes test/functional/xlsx_files/sparkline03.xlsx | Bin 0 -> 5167 bytes test/functional/xlsx_files/textbox01.xlsx | Bin 0 -> 8091 bytes test/unit/chart/test_chart.c | 4 +- 508 files changed, 9011 insertions(+), 1321 deletions(-) create mode 100644 docs/WINDOWS_BUILD.md create mode 100644 examples/chart_combined.c create mode 100644 examples/chart_gauge.c create mode 100644 examples/chart_gradient.c create mode 100644 examples/chart_pareto.c create mode 100644 examples/chart_secondary_axis.c create mode 100644 examples/chart_stock.c create mode 100644 examples/checkbox.c create mode 100644 examples/colors.c create mode 100644 examples/right_to_left.c create mode 100644 examples/sparklines.c create mode 100644 examples/text_indent.c create mode 100644 examples/textbox.c create mode 100644 include/xlsxwriter/feature_property_bag.h create mode 100644 include/xlsxwriter/sparkline.h create mode 100644 src/feature_property_bag.c create mode 100644 src/labview_wrappers.c create mode 100644 test/functional/src/test_autofit01.c create mode 100644 test/functional/src/test_chart_area04.c create mode 100644 test/functional/src/test_chart_bar24.c create mode 100644 test/functional/src/test_chart_clustered01.c create mode 100644 test/functional/src/test_chart_column04.c create mode 100644 test/functional/src/test_chart_combined01.c create mode 100644 test/functional/src/test_chart_combined02.c create mode 100644 test/functional/src/test_chart_combined03.c create mode 100644 test/functional/src/test_chart_combined04.c create mode 100644 test/functional/src/test_chart_combined05.c create mode 100644 test/functional/src/test_chart_combined06.c create mode 100644 test/functional/src/test_chart_combined07.c create mode 100644 test/functional/src/test_chart_combined08.c create mode 100644 test/functional/src/test_chart_combined09.c create mode 100644 test/functional/src/test_chart_combined10.c create mode 100644 test/functional/src/test_chart_combined11.c create mode 100644 test/functional/src/test_chart_date01.c create mode 100644 test/functional/src/test_chart_gap04.c create mode 100644 test/functional/src/test_chart_gap05.c create mode 100644 test/functional/src/test_chart_gradient01.c create mode 100644 test/functional/src/test_chart_gradient02.c create mode 100644 test/functional/src/test_chart_gradient03.c create mode 100644 test/functional/src/test_chart_gradient04.c create mode 100644 test/functional/src/test_chart_gradient05.c create mode 100644 test/functional/src/test_chart_gradient06.c create mode 100644 test/functional/src/test_chart_gradient07.c create mode 100644 test/functional/src/test_chart_gradient08.c create mode 100644 test/functional/src/test_chart_gradient09.c create mode 100644 test/functional/src/test_chart_gradient10.c create mode 100644 test/functional/src/test_chart_gradient11.c create mode 100644 test/functional/src/test_chart_gradient12.c create mode 100644 test/functional/src/test_chart_gradient13.c create mode 100644 test/functional/src/test_chart_line02.c create mode 100644 test/functional/src/test_chart_line07.c create mode 100644 test/functional/src/test_chart_line08.c create mode 100644 test/functional/src/test_chart_scatter07.c create mode 100644 test/functional/src/test_chart_stock01.c create mode 100644 test/functional/src/test_chart_stock02.c create mode 100644 test/functional/src/test_chart_stock03.c create mode 100644 test/functional/src/test_checkbox01.c create mode 100644 test/functional/src/test_sparkline01.c create mode 100644 test/functional/src/test_sparkline02.c create mode 100644 test/functional/src/test_sparkline03.c create mode 100644 test/functional/src/test_textbox01.c create mode 100644 test/functional/test_autofit.py create mode 100644 test/functional/test_chart_combined.py create mode 100644 test/functional/test_chart_date.py create mode 100644 test/functional/test_chart_stock.py create mode 100644 test/functional/test_checkbox.py create mode 100644 test/functional/test_sparkline.py create mode 100644 test/functional/test_textbox.py create mode 100644 test/functional/xlsx_files/autofit01.xlsx create mode 100644 test/functional/xlsx_files/autofit02.xlsx create mode 100644 test/functional/xlsx_files/autofit03.xlsx create mode 100644 test/functional/xlsx_files/autofit04.xlsx create mode 100644 test/functional/xlsx_files/autofit05.xlsx create mode 100644 test/functional/xlsx_files/autofit06.xlsx create mode 100644 test/functional/xlsx_files/autofit07.xlsx create mode 100644 test/functional/xlsx_files/autofit08.xlsx create mode 100644 test/functional/xlsx_files/autofit09.xlsx create mode 100644 test/functional/xlsx_files/autofit10.xlsx create mode 100644 test/functional/xlsx_files/autofit11.xlsx create mode 100644 test/functional/xlsx_files/autofit12.xlsx create mode 100644 test/functional/xlsx_files/autofit13.xlsx create mode 100644 test/functional/xlsx_files/autofit14.xlsx create mode 100644 test/functional/xlsx_files/chart_area04.xlsx create mode 100644 test/functional/xlsx_files/chart_bar24.xlsx create mode 100644 test/functional/xlsx_files/chart_clustered01.xlsx create mode 100644 test/functional/xlsx_files/chart_column04.xlsx create mode 100644 test/functional/xlsx_files/chart_combined01.xlsx create mode 100644 test/functional/xlsx_files/chart_combined02.xlsx create mode 100644 test/functional/xlsx_files/chart_combined03.xlsx create mode 100644 test/functional/xlsx_files/chart_combined04.xlsx create mode 100644 test/functional/xlsx_files/chart_combined05.xlsx create mode 100644 test/functional/xlsx_files/chart_combined06.xlsx create mode 100644 test/functional/xlsx_files/chart_combined07.xlsx create mode 100644 test/functional/xlsx_files/chart_combined08.xlsx create mode 100644 test/functional/xlsx_files/chart_combined09.xlsx create mode 100644 test/functional/xlsx_files/chart_combined10.xlsx create mode 100644 test/functional/xlsx_files/chart_combined11.xlsx create mode 100644 test/functional/xlsx_files/chart_date01.xlsx create mode 100644 test/functional/xlsx_files/chart_date02.xlsx create mode 100644 test/functional/xlsx_files/chart_date03.xlsx create mode 100644 test/functional/xlsx_files/chart_date04.xlsx create mode 100644 test/functional/xlsx_files/chart_date05.xlsx create mode 100644 test/functional/xlsx_files/chart_gap04.xlsx create mode 100644 test/functional/xlsx_files/chart_gap05.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient01.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient02.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient03.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient04.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient05.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient06.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient07.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient08.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient09.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient10.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient11.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient12.xlsx create mode 100644 test/functional/xlsx_files/chart_gradient13.xlsx create mode 100644 test/functional/xlsx_files/chart_line02.xlsx create mode 100644 test/functional/xlsx_files/chart_line07.xlsx create mode 100644 test/functional/xlsx_files/chart_line08.xlsx create mode 100644 test/functional/xlsx_files/chart_scatter07.xlsx create mode 100644 test/functional/xlsx_files/chart_stock01.xlsx create mode 100644 test/functional/xlsx_files/chart_stock02.xlsx create mode 100644 test/functional/xlsx_files/chart_stock03.xlsx create mode 100644 test/functional/xlsx_files/checkbox01.xlsx create mode 100644 test/functional/xlsx_files/sparkline01.xlsx create mode 100644 test/functional/xlsx_files/sparkline02.xlsx create mode 100644 test/functional/xlsx_files/sparkline03.xlsx create mode 100644 test/functional/xlsx_files/textbox01.xlsx diff --git a/.indent.pro b/.indent.pro index 1b790cc6..59986d3c 100644 --- a/.indent.pro +++ b/.indent.pro @@ -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 diff --git a/Changes.txt b/Changes.txt index 5e377d90..f8ef8407 100644 --- a/Changes.txt +++ b/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 diff --git a/build.zig b/build.zig index fb05d9ad..a4450916 100644 --- a/build.zig +++ b/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(.{ diff --git a/build.zig.zon b/build.zig.zon index 620dff38..cf555ae9 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -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", diff --git a/dev/fuzzing/build.sh b/dev/fuzzing/build.sh index 6057cc89..f3c93ecd 100755 --- a/dev/fuzzing/build.sh +++ b/dev/fuzzing/build.sh @@ -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 diff --git a/docs/WINDOWS_BUILD.md b/docs/WINDOWS_BUILD.md new file mode 100644 index 00000000..628e43ba --- /dev/null +++ b/docs/WINDOWS_BUILD.md @@ -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/) diff --git a/docs/src/working_with_charts.dox b/docs/src/working_with_charts.dox index b41c2d67..af503b6d 100644 --- a/docs/src/working_with_charts.dox +++ b/docs/src/working_with_charts.dox @@ -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 diff --git a/examples/chart.c b/examples/chart.c index 0fb1b738..fccd6882 100644 --- a/examples/chart.c +++ b/examples/chart.c @@ -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}; diff --git a/examples/chart_area.c b/examples/chart_area.c index 4f486f71..c101e00e 100644 --- a/examples/chart_area.c +++ b/examples/chart_area.c @@ -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"); diff --git a/examples/chart_bar.c b/examples/chart_bar.c index 5f710e20..3120c8fb 100644 --- a/examples/chart_bar.c +++ b/examples/chart_bar.c @@ -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"); diff --git a/examples/chart_clustered.c b/examples/chart_clustered.c index 1acf4d7b..ef88eeed 100644 --- a/examples/chart_clustered.c +++ b/examples/chart_clustered.c @@ -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); diff --git a/examples/chart_column.c b/examples/chart_column.c index 86ff701e..0f8fe79e 100644 --- a/examples/chart_column.c +++ b/examples/chart_column.c @@ -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"); diff --git a/examples/chart_combined.c b/examples/chart_combined.c new file mode 100644 index 00000000..f2793217 --- /dev/null +++ b/examples/chart_combined.c @@ -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); +} diff --git a/examples/chart_data_labels.c b/examples/chart_data_labels.c index 8b70782a..acfe2b7f 100644 --- a/examples/chart_data_labels.c +++ b/examples/chart_data_labels.c @@ -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); diff --git a/examples/chart_data_table.c b/examples/chart_data_table.c index 94a1226f..cfc6c74a 100644 --- a/examples/chart_data_table.c +++ b/examples/chart_data_table.c @@ -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"); diff --git a/examples/chart_data_tools.c b/examples/chart_data_tools.c index 2b7661a0..dc5852f8 100644 --- a/examples/chart_data_tools.c +++ b/examples/chart_data_tools.c @@ -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, diff --git a/examples/chart_doughnut.c b/examples/chart_doughnut.c index be67df42..b8b976eb 100644 --- a/examples/chart_doughnut.c +++ b/examples/chart_doughnut.c @@ -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"); diff --git a/examples/chart_fonts.c b/examples/chart_fonts.c index ecd9c2d5..b3b37674 100644 --- a/examples/chart_fonts.c +++ b/examples/chart_fonts.c @@ -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}; diff --git a/examples/chart_gauge.c b/examples/chart_gauge.c new file mode 100644 index 00000000..f0523543 --- /dev/null +++ b/examples/chart_gauge.c @@ -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); +} diff --git a/examples/chart_gradient.c b/examples/chart_gradient.c new file mode 100644 index 00000000..14d081a5 --- /dev/null +++ b/examples/chart_gradient.c @@ -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); +} diff --git a/examples/chart_line.c b/examples/chart_line.c index 2094decc..6120340c 100644 --- a/examples/chart_line.c +++ b/examples/chart_line.c @@ -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"); diff --git a/examples/chart_pareto.c b/examples/chart_pareto.c new file mode 100644 index 00000000..1f277a62 --- /dev/null +++ b/examples/chart_pareto.c @@ -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); +} diff --git a/examples/chart_pattern.c b/examples/chart_pattern.c index 1cb2b498..b0b7c694 100644 --- a/examples/chart_pattern.c +++ b/examples/chart_pattern.c @@ -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"); diff --git a/examples/chart_pie.c b/examples/chart_pie.c index 2df4652d..53da939a 100644 --- a/examples/chart_pie.c +++ b/examples/chart_pie.c @@ -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"); diff --git a/examples/chart_pie_colors.c b/examples/chart_pie_colors.c index cc3ff73c..f6cc1497 100644 --- a/examples/chart_pie_colors.c +++ b/examples/chart_pie_colors.c @@ -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 }; diff --git a/examples/chart_radar.c b/examples/chart_radar.c index f9fdf4bc..21375361 100644 --- a/examples/chart_radar.c +++ b/examples/chart_radar.c @@ -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"); diff --git a/examples/chart_scatter.c b/examples/chart_scatter.c index 1f9c5429..d93af2df 100644 --- a/examples/chart_scatter.c +++ b/examples/chart_scatter.c @@ -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"); diff --git a/examples/chart_secondary_axis.c b/examples/chart_secondary_axis.c new file mode 100644 index 00000000..c227c3e9 --- /dev/null +++ b/examples/chart_secondary_axis.c @@ -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); +} diff --git a/examples/chart_stock.c b/examples/chart_stock.c new file mode 100644 index 00000000..c8bb2da0 --- /dev/null +++ b/examples/chart_stock.c @@ -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); +} diff --git a/examples/chart_styles.c b/examples/chart_styles.c index 4a851216..f1dac5cb 100644 --- a/examples/chart_styles.c +++ b/examples/chart_styles.c @@ -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); diff --git a/examples/chart_working_with_example.c b/examples/chart_working_with_example.c index 6344207d..4b572d26 100644 --- a/examples/chart_working_with_example.c +++ b/examples/chart_working_with_example.c @@ -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. */ diff --git a/examples/chartsheet.c b/examples/chartsheet.c index 7896badd..6af50de5 100644 --- a/examples/chartsheet.c +++ b/examples/chartsheet.c @@ -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" */ diff --git a/examples/checkbox.c b/examples/checkbox.c new file mode 100644 index 00000000..19e39b89 --- /dev/null +++ b/examples/checkbox.c @@ -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; +} diff --git a/examples/colors.c b/examples/colors.c new file mode 100644 index 00000000..78b04e8c --- /dev/null +++ b/examples/colors.c @@ -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); +} diff --git a/examples/right_to_left.c b/examples/right_to_left.c new file mode 100644 index 00000000..a783fa57 --- /dev/null +++ b/examples/right_to_left.c @@ -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); +} diff --git a/examples/sparklines.c b/examples/sparklines.c new file mode 100644 index 00000000..6563c880 --- /dev/null +++ b/examples/sparklines.c @@ -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); +} diff --git a/examples/text_indent.c b/examples/text_indent.c new file mode 100644 index 00000000..1ea626a7 --- /dev/null +++ b/examples/text_indent.c @@ -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); +} diff --git a/examples/textbox.c b/examples/textbox.c new file mode 100644 index 00000000..84a522aa --- /dev/null +++ b/examples/textbox.c @@ -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; +} diff --git a/include/xlsxwriter.h b/include/xlsxwriter.h index fb41018b..e395ad12 100644 --- a/include/xlsxwriter.h +++ b/include/xlsxwriter.h @@ -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__ */ diff --git a/include/xlsxwriter/chart.h b/include/xlsxwriter/chart.h index b4fc053b..3c6e2285 100644 --- a/include/xlsxwriter/chart.h +++ b/include/xlsxwriter/chart.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,51 @@ 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 +1112,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 +1138,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 +1157,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 +1218,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 +1250,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 +1265,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 +1285,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 +1296,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 +1320,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 +1377,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 +1390,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 +1414,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 +1459,30 @@ 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 +1685,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 +2647,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 +3309,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 +3801,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 +3874,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 +4149,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. * diff --git a/include/xlsxwriter/common.h b/include/xlsxwriter/common.h index f7b281f6..2b793223 100644 --- a/include/xlsxwriter/common.h +++ b/include/xlsxwriter/common.h @@ -110,9 +110,6 @@ typedef enum lxw_error { /** Function string parameter is empty. */ LXW_ERROR_PARAMETER_IS_EMPTY, - /** A #lxw_datetime parameter has a validation error. */ - LXW_ERROR_DATETIME_VALIDATION, - /** Worksheet name exceeds Excel's limit of 31 characters. */ LXW_ERROR_SHEETNAME_LENGTH_EXCEEDED, diff --git a/include/xlsxwriter/content_types.h b/include/xlsxwriter/content_types.h index bbe967d5..c62a75ea 100644 --- a/include/xlsxwriter/content_types.h +++ b/include/xlsxwriter/content_types.h @@ -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 diff --git a/include/xlsxwriter/drawing.h b/include/xlsxwriter/drawing.h index 10105cb9..5b95a612 100644 --- a/include/xlsxwriter/drawing.h +++ b/include/xlsxwriter/drawing.h @@ -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; diff --git a/include/xlsxwriter/feature_property_bag.h b/include/xlsxwriter/feature_property_bag.h new file mode 100644 index 00000000..5e203c3a --- /dev/null +++ b/include/xlsxwriter/feature_property_bag.h @@ -0,0 +1,58 @@ +/* + * 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 + +#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__ */ diff --git a/include/xlsxwriter/format.h b/include/xlsxwriter/format.h index 471c27db..e16853ee 100644 --- a/include/xlsxwriter/format.h +++ b/include/xlsxwriter/format.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); diff --git a/include/xlsxwriter/packager.h b/include/xlsxwriter/packager.h index 2e7f8a5a..244a459a 100644 --- a/include/xlsxwriter/packager.h +++ b/include/xlsxwriter/packager.h @@ -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) diff --git a/include/xlsxwriter/relationships.h b/include/xlsxwriter/relationships.h index f989cc97..a5244dfe 100644 --- a/include/xlsxwriter/relationships.h +++ b/include/xlsxwriter/relationships.h @@ -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 diff --git a/include/xlsxwriter/sparkline.h b/include/xlsxwriter/sparkline.h new file mode 100644 index 00000000..e99469ac --- /dev/null +++ b/include/xlsxwriter/sparkline.h @@ -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__ */ diff --git a/include/xlsxwriter/utility.h b/include/xlsxwriter/utility.h index 075bdcff..6653f1af 100644 --- a/include/xlsxwriter/utility.h +++ b/include/xlsxwriter/utility.h @@ -212,30 +212,6 @@ double lxw_datetime_to_excel_datetime(lxw_datetime *datetime); double lxw_datetime_to_excel_date_with_epoch(lxw_datetime *datetime, uint8_t use_1904_epoch); -/** - * @brief Validate a #lxw_datetime struct. - * - * Validates a #lxw_datetime struct to ensure its fields are within acceptable - * ranges for Excel dates and times. - * - * The members of the #lxw_datetime struct and the range of their values are: - * - * Member | Value - * -------- | ----------- - * year | 1900 - 9999 - * month | 1 - 12 - * day | 1 - 31 - * hour | 0 - 23 - * min | 0 - 59 - * sec | 0 - 59.999 - * - * @param datetime A pointer to a #lxw_datetime struct. - * - * @return A #lxw_error code. Either #LXW_NO_ERROR or - * #LXW_ERROR_DATETIME_VALIDATION if a field is out of range. - */ -lxw_error lxw_datetime_validate(lxw_datetime *datetime); - /** * @brief Converts a unix datetime to an Excel datetime number. * @@ -300,6 +276,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 } diff --git a/include/xlsxwriter/workbook.h b/include/xlsxwriter/workbook.h index f10f1f5e..75f01ba7 100644 --- a/include/xlsxwriter/workbook.h +++ b/include/xlsxwriter/workbook.h @@ -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; diff --git a/include/xlsxwriter/worksheet.h b/include/xlsxwriter/worksheet.h index 9a3bfb93..26f899d7 100644 --- a/include/xlsxwriter/worksheet.h +++ b/include/xlsxwriter/worksheet.h @@ -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,36 @@ 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 +4100,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 +4615,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 +6062,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, diff --git a/src/chart.c b/src/chart.c index 46680b87..982e0c4a 100644 --- a/src/chart.c +++ b/src/chart.c @@ -139,10 +139,12 @@ _chart_series_free(lxw_chart_series *series) free(series->line); free(series->fill); free(series->pattern); + free(series->gradient); free(series->label_num_format); free(series->label_line); free(series->label_fill); free(series->label_pattern); + free(series->label_gradient); _chart_free_font(series->label_font); @@ -216,6 +218,10 @@ lxw_chart_free(lxw_chart *chart) _chart_free_axis(chart->x_axis); _chart_free_axis(chart->y_axis); + /* Secondary X2 and Y2 Axis. */ + _chart_free_axis(chart->x2_axis); + _chart_free_axis(chart->y2_axis); + /* Chart title. */ _chart_free_font(chart->title.font); _chart_free_range(chart->title.range); @@ -232,11 +238,13 @@ lxw_chart_free(lxw_chart *chart) free(chart->chartarea_line); free(chart->chartarea_fill); free(chart->chartarea_pattern); + free(chart->chartarea_gradient); free(chart->plotarea_line); free(chart->plotarea_fill); free(chart->plotarea_layout); free(chart->plotarea_pattern); + free(chart->plotarea_gradient); free(chart->drop_lines_line); free(chart->high_low_lines_line); @@ -270,6 +278,12 @@ lxw_chart_new(uint8_t type) chart->y_axis = calloc(1, sizeof(struct lxw_chart_axis)); GOTO_LABEL_ON_MEM_ERROR(chart->y_axis, mem_error); + chart->x2_axis = calloc(1, sizeof(struct lxw_chart_axis)); + GOTO_LABEL_ON_MEM_ERROR(chart->x2_axis, mem_error); + + chart->y2_axis = calloc(1, sizeof(struct lxw_chart_axis)); + GOTO_LABEL_ON_MEM_ERROR(chart->y2_axis, mem_error); + chart->title.range = calloc(1, sizeof(lxw_series_range)); GOTO_LABEL_ON_MEM_ERROR(chart->title.range, mem_error); @@ -279,6 +293,12 @@ lxw_chart_new(uint8_t type) chart->y_axis->title.range = calloc(1, sizeof(lxw_series_range)); GOTO_LABEL_ON_MEM_ERROR(chart->y_axis->title.range, mem_error); + chart->x2_axis->title.range = calloc(1, sizeof(lxw_series_range)); + GOTO_LABEL_ON_MEM_ERROR(chart->x2_axis->title.range, mem_error); + + chart->y2_axis->title.range = calloc(1, sizeof(lxw_series_range)); + GOTO_LABEL_ON_MEM_ERROR(chart->y2_axis->title.range, mem_error); + /* Initialize the ranges in the chart titles. */ if (_chart_init_data_cache(chart->title.range) != LXW_NO_ERROR) goto mem_error; @@ -289,6 +309,12 @@ lxw_chart_new(uint8_t type) if (_chart_init_data_cache(chart->y_axis->title.range) != LXW_NO_ERROR) goto mem_error; + if (_chart_init_data_cache(chart->x2_axis->title.range) != LXW_NO_ERROR) + goto mem_error; + + if (_chart_init_data_cache(chart->y2_axis->title.range) != LXW_NO_ERROR) + goto mem_error; + chart->type = type; chart->style_id = 2; chart->hole_size = 50; @@ -297,12 +323,22 @@ lxw_chart_new(uint8_t type) chart->x_axis->axis_position = LXW_CHART_AXIS_BOTTOM; chart->y_axis->axis_position = LXW_CHART_AXIS_LEFT; + /* Set the default secondary axis positions and properties. */ + chart->x2_axis->axis_position = LXW_CHART_AXIS_BOTTOM; /* Same as primary X axis */ + chart->y2_axis->axis_position = LXW_CHART_AXIS_RIGHT; + chart->x2_axis->hidden = LXW_TRUE; /* Secondary X axis hidden by default */ + chart->y2_axis->crossing_max = LXW_TRUE; /* Secondary Y axis crosses at max */ + /* Set the default axis number formats. */ _chart_axis_set_default_num_format(chart->x_axis, "General"); _chart_axis_set_default_num_format(chart->y_axis, "General"); + _chart_axis_set_default_num_format(chart->x2_axis, "General"); + _chart_axis_set_default_num_format(chart->y2_axis, "General"); chart->x_axis->major_gridlines.visible = LXW_FALSE; chart->y_axis->major_gridlines.visible = LXW_TRUE; + chart->x2_axis->major_gridlines.visible = LXW_FALSE; + chart->y2_axis->major_gridlines.visible = LXW_FALSE; chart->has_horiz_cat_axis = LXW_FALSE; chart->has_horiz_val_axis = LXW_TRUE; @@ -448,6 +484,64 @@ _chart_convert_pattern_args(lxw_chart_pattern *user_pattern) return pattern; } +/* + * Create a copy of a user supplied gradient. + */ +STATIC lxw_chart_gradient_fill * +_chart_convert_gradient_args(lxw_chart_gradient_fill *user_gradient) +{ + lxw_chart_gradient_fill *gradient; + uint8_t i; + + if (!user_gradient) + return NULL; + + if (user_gradient->num_stops < 2 || + user_gradient->num_stops > LXW_CHART_GRADIENT_MAX_STOPS) { + LXW_WARN("chart_xxx_set_gradient: 'num_stops' must be 2-10"); + return NULL; + } + + gradient = calloc(1, sizeof(struct lxw_chart_gradient_fill)); + RETURN_ON_MEM_ERROR(gradient, NULL); + + /* Copy the user supplied properties. */ + gradient->type = user_gradient->type; + gradient->num_stops = user_gradient->num_stops; + gradient->angle = user_gradient->angle; + + /* Set default angle for linear gradients. */ + if (gradient->type == LXW_CHART_GRADIENT_FILL_LINEAR + && gradient->angle == 0) + gradient->angle = 90; + + for (i = 0; i < gradient->num_stops; i++) { + gradient->colors[i] = user_gradient->colors[i]; + gradient->positions[i] = user_gradient->positions[i]; + } + + /* Set default positions if not specified. */ + if (gradient->positions[0] == 0 && gradient->positions[1] == 0) { + if (gradient->num_stops == 2) { + gradient->positions[0] = 0; + gradient->positions[1] = 100; + } + else if (gradient->num_stops == 3) { + gradient->positions[0] = 0; + gradient->positions[1] = 50; + gradient->positions[2] = 100; + } + else if (gradient->num_stops == 4) { + gradient->positions[0] = 0; + gradient->positions[1] = 33; + gradient->positions[2] = 66; + gradient->positions[3] = 100; + } + } + + return gradient; +} + /* * Create a copy of a user supplied layout. */ @@ -559,7 +653,7 @@ _chart_check_error_bars(lxw_series_error_bars *error_bars, char *property) } /* - * Add unique ids for primary or secondary axes. + * Add unique ids for primary axes. */ STATIC void _chart_add_axis_ids(lxw_chart *self) @@ -571,6 +665,23 @@ _chart_add_axis_ids(lxw_chart *self) self->axis_id_2 = self->axis_id_1 + 1; } +/* + * Add unique ids for secondary axes. + */ +STATIC void +_chart_add_axis_ids_2(lxw_chart *self) +{ + uint32_t chart_id = 50010000 + self->id; + uint32_t axis_count = 1; + + /* Secondary axes continue from primary axis count. */ + if (self->axis_id_1) + axis_count = 3; + + self->axis_id_3 = chart_id + axis_count; + self->axis_id_4 = self->axis_id_3 + 1; +} + /* * Utility function to set a chart range. */ @@ -2012,19 +2123,204 @@ _chart_write_a_patt_fill(lxw_chart *self, lxw_chart_pattern *pattern) } /* - * Write the element. + * Write the element for a gradient stop. */ STATIC void -_chart_write_sp_pr(lxw_chart *self, lxw_chart_line *line, - lxw_chart_fill *fill, lxw_chart_pattern *pattern) +_chart_write_a_gs(lxw_chart *self, uint8_t position, lxw_color_t color) { - if (!line && !fill && !pattern) + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + + LXW_INIT_ATTRIBUTES(); + LXW_PUSH_ATTRIBUTES_INT("pos", position * 1000); + + lxw_xml_start_tag(self->file, "a:gs", &attributes); + + _chart_write_a_srgb_clr(self, color, LXW_FALSE); + + lxw_xml_end_tag(self->file, "a:gs"); + + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the element for gradient stops. + */ +STATIC void +_chart_write_a_gs_lst(lxw_chart *self, lxw_chart_gradient_fill *gradient) +{ + uint8_t i; + + lxw_xml_start_tag(self->file, "a:gsLst", NULL); + + for (i = 0; i < gradient->num_stops; i++) { + _chart_write_a_gs(self, gradient->positions[i], gradient->colors[i]); + } + + lxw_xml_end_tag(self->file, "a:gsLst"); +} + +/* + * Write the element for linear gradient angle. + */ +STATIC void +_chart_write_a_lin(lxw_chart *self, uint16_t angle) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + + LXW_INIT_ATTRIBUTES(); + LXW_PUSH_ATTRIBUTES_INT("ang", angle * 60000); + LXW_PUSH_ATTRIBUTES_STR("scaled", "0"); + + lxw_xml_empty_tag(self->file, "a:lin", &attributes); + + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the element for path gradients. + */ +STATIC void +_chart_write_a_fill_to_rect(lxw_chart *self, uint8_t gradient_type) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + + LXW_INIT_ATTRIBUTES(); + + if (gradient_type == LXW_CHART_GRADIENT_FILL_PATH) { + LXW_PUSH_ATTRIBUTES_STR("l", "50000"); + LXW_PUSH_ATTRIBUTES_STR("t", "50000"); + LXW_PUSH_ATTRIBUTES_STR("r", "50000"); + LXW_PUSH_ATTRIBUTES_STR("b", "50000"); + } + else { + LXW_PUSH_ATTRIBUTES_STR("l", "100000"); + LXW_PUSH_ATTRIBUTES_STR("t", "100000"); + } + + lxw_xml_empty_tag(self->file, "a:fillToRect", &attributes); + + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the element for non-linear gradients. + */ +STATIC void +_chart_write_a_gradient_path(lxw_chart *self, uint8_t gradient_type) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + char *path_str = "shape"; + + LXW_INIT_ATTRIBUTES(); + + if (gradient_type == LXW_CHART_GRADIENT_FILL_RADIAL) + path_str = "circle"; + else if (gradient_type == LXW_CHART_GRADIENT_FILL_RECTANGULAR) + path_str = "rect"; + else if (gradient_type == LXW_CHART_GRADIENT_FILL_PATH) + path_str = "shape"; + + LXW_PUSH_ATTRIBUTES_STR("path", path_str); + + lxw_xml_start_tag(self->file, "a:path", &attributes); + + _chart_write_a_fill_to_rect(self, gradient_type); + + lxw_xml_end_tag(self->file, "a:path"); + + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the element for non-linear gradients. + */ +STATIC void +_chart_write_a_tile_rect(lxw_chart *self, uint8_t gradient_type) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + + LXW_INIT_ATTRIBUTES(); + + if (gradient_type != LXW_CHART_GRADIENT_FILL_PATH) { + LXW_PUSH_ATTRIBUTES_STR("r", "-100000"); + LXW_PUSH_ATTRIBUTES_STR("b", "-100000"); + } + + lxw_xml_empty_tag(self->file, "a:tileRect", &attributes); + + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the element. + */ +STATIC void +_chart_write_a_grad_fill(lxw_chart *self, lxw_chart_gradient_fill *gradient) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + + if (!gradient) + return; + + LXW_INIT_ATTRIBUTES(); + + if (gradient->type != LXW_CHART_GRADIENT_FILL_LINEAR) { + LXW_PUSH_ATTRIBUTES_STR("flip", "none"); + LXW_PUSH_ATTRIBUTES_STR("rotWithShape", "1"); + } + + lxw_xml_start_tag(self->file, "a:gradFill", &attributes); + + /* Write the a:gsLst element. */ + _chart_write_a_gs_lst(self, gradient); + + if (gradient->type == LXW_CHART_GRADIENT_FILL_LINEAR) { + /* Write the a:lin element. */ + _chart_write_a_lin(self, gradient->angle); + } + else { + /* Write the a:path element. */ + _chart_write_a_gradient_path(self, gradient->type); + + /* Write the a:tileRect element. */ + _chart_write_a_tile_rect(self, gradient->type); + } + + lxw_xml_end_tag(self->file, "a:gradFill"); + + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the element with gradient support. + */ +STATIC void +_chart_write_sp_pr_with_gradient(lxw_chart *self, lxw_chart_line *line, + lxw_chart_fill *fill, + lxw_chart_pattern *pattern, + lxw_chart_gradient_fill *gradient) +{ + if (!line && !fill && !pattern && !gradient) return; lxw_xml_start_tag(self->file, "c:spPr", NULL); - /* Write the series fill. Note: a pattern fill overrides a solid fill. */ - if (fill && !pattern) { + /* Write the fill. Priority: gradient > pattern > solid fill. */ + if (gradient) { + /* Write the a:gradFill element. */ + _chart_write_a_grad_fill(self, gradient); + } + else if (pattern) { + /* Write the a:pattFill element. */ + _chart_write_a_patt_fill(self, pattern); + } + else if (fill) { if (fill->none) { /* Write the a:noFill element. */ _chart_write_a_no_fill(self); @@ -2035,11 +2331,6 @@ _chart_write_sp_pr(lxw_chart *self, lxw_chart_line *line, } } - if (pattern) { - /* Write the a:pattFill element. */ - _chart_write_a_patt_fill(self, pattern); - } - if (line) { /* Write the a:ln element. */ _chart_write_a_ln(self, line); @@ -2048,6 +2339,16 @@ _chart_write_sp_pr(lxw_chart *self, lxw_chart_line *line, lxw_xml_end_tag(self->file, "c:spPr"); } +/* + * Write the element. + */ +STATIC void +_chart_write_sp_pr(lxw_chart *self, lxw_chart_line *line, + lxw_chart_fill *fill, lxw_chart_pattern *pattern) +{ + _chart_write_sp_pr_with_gradient(self, line, fill, pattern, NULL); +} + /* * Write the element. */ @@ -2083,7 +2384,7 @@ _chart_write_axis_id(lxw_chart *self, uint32_t axis_id) } /* - * Write the element. + * Write the element for primary axes. */ STATIC void _chart_write_axis_ids(lxw_chart *self) @@ -2095,6 +2396,19 @@ _chart_write_axis_ids(lxw_chart *self) _chart_write_axis_id(self, self->axis_id_2); } +/* + * Write the element for secondary axes. + */ +STATIC void +_chart_write_axis_ids_2(lxw_chart *self) +{ + if (!self->axis_id_3) + _chart_add_axis_ids_2(self); + + _chart_write_axis_id(self, self->axis_id_3); + _chart_write_axis_id(self, self->axis_id_4); +} + /* * Write the series name. */ @@ -2197,6 +2511,8 @@ _chart_write_symbol(lxw_chart *self, uint8_t type) LXW_PUSH_ATTRIBUTES_STR("val", "circle"); else if (type == LXW_CHART_MARKER_PLUS) LXW_PUSH_ATTRIBUTES_STR("val", "plus"); + else if (type == LXW_CHART_MARKER_DOT) + LXW_PUSH_ATTRIBUTES_STR("val", "dot"); else LXW_PUSH_ATTRIBUTES_STR("val", "none"); @@ -3213,7 +3529,8 @@ _chart_write_ser(lxw_chart *self, lxw_chart_series *series) _chart_write_series_name(self, series); /* Write the c:spPr element. */ - _chart_write_sp_pr(self, series->line, series->fill, series->pattern); + _chart_write_sp_pr_with_gradient(self, series->line, series->fill, + series->pattern, series->gradient); /* Write the c:marker element. */ _chart_write_marker(self, series->marker); @@ -3268,7 +3585,8 @@ _chart_write_xval_ser(lxw_chart *self, lxw_chart_series *series) _chart_write_series_name(self, series); /* Write the c:spPr element. */ - _chart_write_sp_pr(self, series->line, series->fill, series->pattern); + _chart_write_sp_pr_with_gradient(self, series->line, series->fill, + series->pattern, series->gradient); /* Write the c:marker element. */ _chart_write_marker(self, series->marker); @@ -3451,6 +3769,23 @@ _chart_write_tick_label_pos(lxw_chart *self, lxw_chart_axis *axis) LXW_FREE_ATTRIBUTES(); } +/* + * Write the element with "none" value. + */ +STATIC void +_chart_write_tick_label_pos_none(lxw_chart *self) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + + LXW_INIT_ATTRIBUTES(); + LXW_PUSH_ATTRIBUTES_STR("val", "none"); + + lxw_xml_empty_tag(self->file, "c:tickLblPos", &attributes); + + LXW_FREE_ATTRIBUTES(); +} + /* * Write the element. */ @@ -3629,6 +3964,74 @@ _chart_write_minor_unit(lxw_chart *self, lxw_chart_axis *axis) LXW_FREE_ATTRIBUTES(); } +/* + * Write the element. + */ +STATIC void +_chart_write_major_time_unit(lxw_chart *self, lxw_chart_axis *axis) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + const char *val; + + if (!axis->has_major_unit) + return; + + LXW_INIT_ATTRIBUTES(); + + switch (axis->major_unit_type) { + case LXW_CHART_AXIS_TIME_UNIT_MONTHS: + val = "months"; + break; + case LXW_CHART_AXIS_TIME_UNIT_YEARS: + val = "years"; + break; + default: + val = "days"; + break; + } + + LXW_PUSH_ATTRIBUTES_STR("val", val); + + lxw_xml_empty_tag(self->file, "c:majorTimeUnit", &attributes); + + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the element. + */ +STATIC void +_chart_write_minor_time_unit(lxw_chart *self, lxw_chart_axis *axis) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + const char *val; + + if (!axis->has_minor_unit) + return; + + LXW_INIT_ATTRIBUTES(); + + switch (axis->minor_unit_type) { + case LXW_CHART_AXIS_TIME_UNIT_MONTHS: + val = "months"; + break; + case LXW_CHART_AXIS_TIME_UNIT_YEARS: + val = "years"; + break; + default: + val = "days"; + break; + } + + LXW_PUSH_ATTRIBUTES_STR("val", val); + + lxw_xml_empty_tag(self->file, "c:minorTimeUnit", &attributes); + + LXW_FREE_ATTRIBUTES(); +} + /* * Write the element. */ @@ -4431,6 +4834,90 @@ _chart_write_cat_axis(lxw_chart *self) lxw_xml_end_tag(self->file, "c:catAx"); } +/* + * Write the element (for stock charts). + */ +STATIC void +_chart_write_date_axis(lxw_chart *self) +{ + lxw_xml_start_tag(self->file, "c:dateAx", NULL); + + _chart_write_axis_id(self, self->axis_id_1); + + /* Write the c:scaling element. */ + _chart_write_scaling(self, + self->x_axis->reverse, + self->x_axis->has_min, self->x_axis->min, + self->x_axis->has_max, self->x_axis->max, 0); + + /* Write the c:delete element to hide axis. */ + if (self->x_axis->hidden) + _chart_write_delete(self); + + /* Write the c:axPos element. */ + _chart_write_axis_pos(self, self->x_axis->axis_position, + self->y_axis->reverse); + + /* Write the c:majorGridlines element. */ + _chart_write_major_gridlines(self, self->x_axis); + + /* Write the c:minorGridlines element. */ + _chart_write_minor_gridlines(self, self->x_axis); + + /* Write the axis title elements. */ + self->x_axis->title.is_horizontal = self->has_horiz_cat_axis; + _chart_write_title(self, &self->x_axis->title); + + /* Write the c:numFmt element. */ + _chart_write_cat_number_format(self, self->x_axis); + + /* Write the c:majorTickMark element. */ + _chart_write_major_tick_mark(self, self->x_axis); + + /* Write the c:minorTickMark element. */ + _chart_write_minor_tick_mark(self, self->x_axis); + + /* Write the c:tickLblPos element. */ + _chart_write_tick_label_pos(self, self->x_axis); + + /* Write the c:spPr element for the axis line. */ + _chart_write_sp_pr(self, self->x_axis->line, self->x_axis->fill, + self->x_axis->pattern); + + /* Write the axis font elements. */ + _chart_write_axis_font(self, self->x_axis->num_font); + + /* Write the c:crossAx element. */ + _chart_write_cross_axis(self, self->axis_id_2); + + /* Write the c:crosses element. */ + if (!self->y_axis->has_crossing || self->y_axis->crossing_min + || self->y_axis->crossing_max) + _chart_write_crosses(self, self->y_axis); + else + _chart_write_crosses_at(self, self->y_axis); + + /* Write the c:auto element. */ + _chart_write_auto(self); + + /* Write the c:lblOffset element. */ + _chart_write_label_offset(self); + + /* Write the c:majorUnit element. */ + _chart_write_major_unit(self, self->x_axis); + + /* Write the c:majorTimeUnit element. */ + _chart_write_major_time_unit(self, self->x_axis); + + /* Write the c:minorUnit element. */ + _chart_write_minor_unit(self, self->x_axis); + + /* Write the c:minorTimeUnit element. */ + _chart_write_minor_time_unit(self, self->x_axis); + + lxw_xml_end_tag(self->file, "c:dateAx"); +} + /* * Write the element. */ @@ -4589,6 +5076,209 @@ _chart_write_cat_val_axis(lxw_chart *self) lxw_xml_end_tag(self->file, "c:valAx"); } +/* + * Write the element for secondary Y axis. + */ +STATIC void +_chart_write_val_axis_2(lxw_chart *self) +{ + /* If there are no secondary axis IDs, don't write this element. */ + if (!self->axis_id_3) + return; + + lxw_xml_start_tag(self->file, "c:valAx", NULL); + + _chart_write_axis_id(self, self->axis_id_4); + + /* Write the c:scaling element. */ + _chart_write_scaling(self, + self->y2_axis->reverse, + self->y2_axis->has_min, self->y2_axis->min, + self->y2_axis->has_max, self->y2_axis->max, + self->y2_axis->log_base); + + /* Write the c:delete element to hide axis. */ + if (self->y2_axis->hidden) + _chart_write_delete(self); + + /* Write the c:axPos element. */ + _chart_write_axis_pos(self, self->y2_axis->axis_position, + self->x2_axis->reverse); + + /* Write the c:majorGridlines element. */ + _chart_write_major_gridlines(self, self->y2_axis); + + /* Write the c:minorGridlines element. */ + _chart_write_minor_gridlines(self, self->y2_axis); + + /* Write the axis title elements. */ + self->y2_axis->title.is_horizontal = self->has_horiz_val_axis; + _chart_write_title(self, &self->y2_axis->title); + + /* Write the c:numFmt element. */ + _chart_write_number_format(self, self->y2_axis); + + /* Write the c:majorTickMark element. */ + _chart_write_major_tick_mark(self, self->y2_axis); + + /* Write the c:minorTickMark element. */ + _chart_write_minor_tick_mark(self, self->y2_axis); + + /* Write the c:tickLblPos element. */ + _chart_write_tick_label_pos(self, self->y2_axis); + + /* Write the c:spPr element for the axis line. */ + _chart_write_sp_pr(self, self->y2_axis->line, self->y2_axis->fill, + self->y2_axis->pattern); + + /* Write the axis font elements. */ + _chart_write_axis_font(self, self->y2_axis->num_font); + + /* Write the c:crossAx element. */ + _chart_write_cross_axis(self, self->axis_id_3); + + /* Write the c:crosses element. */ + _chart_write_crosses(self, self->y2_axis); + + /* Write the c:crossBetween element. */ + _chart_write_cross_between(self, self->y2_axis->position_axis); + + /* Write the c:majorUnit element. */ + _chart_write_major_unit(self, self->y2_axis); + + /* Write the c:minorUnit element. */ + _chart_write_minor_unit(self, self->y2_axis); + + /* Write the c:dispUnits element. */ + _chart_write_disp_units(self, self->y2_axis); + + lxw_xml_end_tag(self->file, "c:valAx"); +} + +/* + * Write the element for secondary X axis. + */ +STATIC void +_chart_write_cat_axis_2(lxw_chart *self) +{ + /* If there are no secondary axis IDs, don't write this element. */ + if (!self->axis_id_3) + return; + + lxw_xml_start_tag(self->file, "c:catAx", NULL); + + _chart_write_axis_id(self, self->axis_id_3); + + /* Write the c:scaling element. */ + _chart_write_scaling(self, + self->x2_axis->reverse, + LXW_FALSE, 0.0, LXW_FALSE, 0.0, 0); + + /* Write the c:delete element to hide axis (secondary X axis hidden by default). */ + if (self->x2_axis->hidden) + _chart_write_delete(self); + + /* Write the c:axPos element. */ + _chart_write_axis_pos(self, self->x2_axis->axis_position, + self->y2_axis->reverse); + + /* Write the c:majorGridlines element. */ + _chart_write_major_gridlines(self, self->x2_axis); + + /* Write the c:minorGridlines element. */ + _chart_write_minor_gridlines(self, self->x2_axis); + + /* Write the axis title elements. */ + self->x2_axis->title.is_horizontal = self->has_horiz_cat_axis; + _chart_write_title(self, &self->x2_axis->title); + + /* Write the c:numFmt element. */ + _chart_write_cat_number_format(self, self->x2_axis); + + /* Write the c:majorTickMark element. */ + _chart_write_major_tick_mark(self, self->x2_axis); + + /* Write the c:minorTickMark element. */ + _chart_write_minor_tick_mark(self, self->x2_axis); + + /* Write the c:tickLblPos element. */ + _chart_write_tick_label_pos(self, self->x2_axis); + + /* Write the c:spPr element for the axis line. */ + _chart_write_sp_pr(self, self->x2_axis->line, self->x2_axis->fill, + self->x2_axis->pattern); + + /* Write the axis font elements. */ + _chart_write_axis_font(self, self->x2_axis->num_font); + + /* Write the c:crossAx element. */ + _chart_write_cross_axis(self, self->axis_id_4); + + /* Write the c:crosses element - secondary axis crosses at max. */ + _chart_write_crosses(self, self->y2_axis); + + /* Write the c:auto element. */ + _chart_write_auto(self); + + /* Write the c:lblAlgn element. */ + _chart_write_label_align(self, self->x2_axis); + + /* Write the c:lblOffset element. */ + _chart_write_label_offset(self); + + /* Write the c:tickLblSkip element. */ + _chart_write_tick_label_skip(self, self->x2_axis); + + /* Write the c:tickMarkSkip element. */ + _chart_write_tick_mark_skip(self, self->x2_axis); + + lxw_xml_end_tag(self->file, "c:catAx"); +} + +/* + * Write the element for secondary X axis (used by stock charts). + */ +STATIC void +_chart_write_date_axis_2(lxw_chart *self) +{ + /* If there are no secondary axis IDs, don't write this element. */ + if (!self->axis_id_3) + return; + + lxw_xml_start_tag(self->file, "c:dateAx", NULL); + + _chart_write_axis_id(self, self->axis_id_3); + + /* Write the c:scaling element. */ + _chart_write_scaling(self, + self->x2_axis->reverse, + LXW_FALSE, 0.0, LXW_FALSE, 0.0, 0); + + /* Write the c:delete element (secondary X axis hidden by default). */ + _chart_write_delete(self); + + /* Write the c:axPos element. */ + _chart_write_axis_pos(self, self->x2_axis->axis_position, + self->y2_axis->reverse); + + /* Write the c:numFmt element. */ + _chart_write_cat_number_format(self, self->x2_axis); + + /* Write the c:tickLblPos element (none for hidden secondary axis). */ + _chart_write_tick_label_pos_none(self); + + /* Write the c:crossAx element. */ + _chart_write_cross_axis(self, self->axis_id_4); + + /* Write the c:auto element. */ + _chart_write_auto(self); + + /* Write the c:lblOffset element. */ + _chart_write_label_offset(self); + + lxw_xml_end_tag(self->file, "c:dateAx"); +} + /* * Write the element. */ @@ -4610,9 +5300,25 @@ _chart_write_bar_dir(lxw_chart *self, char *type) * Write a area chart. */ STATIC void -_chart_write_area_chart(lxw_chart *self) +_chart_write_area_chart(lxw_chart *self, uint8_t primary_axes) { lxw_chart_series *series; + uint8_t has_series = LXW_FALSE; + + /* Check if there are any series for this axis type. */ + STAILQ_FOREACH(series, self->series_list, list_pointers) { + if (primary_axes && !series->y2_axis) { + has_series = LXW_TRUE; + break; + } + if (!primary_axes && series->y2_axis) { + has_series = LXW_TRUE; + break; + } + } + + if (!has_series) + return; lxw_xml_start_tag(self->file, "c:areaChart", NULL); @@ -4620,6 +5326,11 @@ _chart_write_area_chart(lxw_chart *self) _chart_write_grouping(self, self->grouping); STAILQ_FOREACH(series, self->series_list, list_pointers) { + /* Only write series for the current axis type. */ + if (primary_axes && series->y2_axis) + continue; + if (!primary_axes && !series->y2_axis) + continue; /* Write the c:ser element. */ _chart_write_ser(self, series); } @@ -4628,7 +5339,10 @@ _chart_write_area_chart(lxw_chart *self) _chart_write_drop_lines(self); /* Write the c:axId elements. */ - _chart_write_axis_ids(self); + if (primary_axes) + _chart_write_axis_ids(self); + else + _chart_write_axis_ids_2(self); lxw_xml_end_tag(self->file, "c:areaChart"); } @@ -4637,9 +5351,25 @@ _chart_write_area_chart(lxw_chart *self) * Write a bar chart. */ STATIC void -_chart_write_bar_chart(lxw_chart *self) +_chart_write_bar_chart(lxw_chart *self, uint8_t primary_axes) { lxw_chart_series *series; + uint8_t has_series = LXW_FALSE; + + /* Check if there are any series for this axis type. */ + STAILQ_FOREACH(series, self->series_list, list_pointers) { + if (primary_axes && !series->y2_axis) { + has_series = LXW_TRUE; + break; + } + if (!primary_axes && series->y2_axis) { + has_series = LXW_TRUE; + break; + } + } + + if (!has_series) + return; lxw_xml_start_tag(self->file, "c:barChart", NULL); @@ -4650,18 +5380,32 @@ _chart_write_bar_chart(lxw_chart *self) _chart_write_grouping(self, self->grouping); STAILQ_FOREACH(series, self->series_list, list_pointers) { + /* Only write series for the current axis type. */ + if (primary_axes && series->y2_axis) + continue; + if (!primary_axes && !series->y2_axis) + continue; /* Write the c:ser element. */ _chart_write_ser(self, series); } /* Write the c:gapWidth element. */ - _chart_write_gap_width(self, self->gap_y1); + if (primary_axes) + _chart_write_gap_width(self, self->gap_y1); + else + _chart_write_gap_width(self, self->gap_y2); /* Write the c:overlap element. */ - _chart_write_overlap(self, self->overlap_y1); + if (primary_axes) + _chart_write_overlap(self, self->overlap_y1); + else + _chart_write_overlap(self, self->overlap_y2); /* Write the c:axId elements. */ - _chart_write_axis_ids(self); + if (primary_axes) + _chart_write_axis_ids(self); + else + _chart_write_axis_ids_2(self); lxw_xml_end_tag(self->file, "c:barChart"); } @@ -4670,9 +5414,25 @@ _chart_write_bar_chart(lxw_chart *self) * Write a column chart. */ STATIC void -_chart_write_column_chart(lxw_chart *self) +_chart_write_column_chart(lxw_chart *self, uint8_t primary_axes) { lxw_chart_series *series; + uint8_t has_series = LXW_FALSE; + + /* Check if there are any series for this axis type. */ + STAILQ_FOREACH(series, self->series_list, list_pointers) { + if (primary_axes && !series->y2_axis) { + has_series = LXW_TRUE; + break; + } + if (!primary_axes && series->y2_axis) { + has_series = LXW_TRUE; + break; + } + } + + if (!has_series) + return; lxw_xml_start_tag(self->file, "c:barChart", NULL); @@ -4683,18 +5443,32 @@ _chart_write_column_chart(lxw_chart *self) _chart_write_grouping(self, self->grouping); STAILQ_FOREACH(series, self->series_list, list_pointers) { + /* Only write series for the current axis type. */ + if (primary_axes && series->y2_axis) + continue; + if (!primary_axes && !series->y2_axis) + continue; /* Write the c:ser element. */ _chart_write_ser(self, series); } /* Write the c:gapWidth element. */ - _chart_write_gap_width(self, self->gap_y1); + if (primary_axes) + _chart_write_gap_width(self, self->gap_y1); + else + _chart_write_gap_width(self, self->gap_y2); /* Write the c:overlap element. */ - _chart_write_overlap(self, self->overlap_y1); + if (primary_axes) + _chart_write_overlap(self, self->overlap_y1); + else + _chart_write_overlap(self, self->overlap_y2); /* Write the c:axId elements. */ - _chart_write_axis_ids(self); + if (primary_axes) + _chart_write_axis_ids(self); + else + _chart_write_axis_ids_2(self); lxw_xml_end_tag(self->file, "c:barChart"); } @@ -4703,10 +5477,14 @@ _chart_write_column_chart(lxw_chart *self) * Write a doughnut chart. */ STATIC void -_chart_write_doughnut_chart(lxw_chart *self) +_chart_write_doughnut_chart(lxw_chart *self, uint8_t primary_axes) { lxw_chart_series *series; + /* Doughnut charts don't support secondary axes. */ + if (!primary_axes) + return; + lxw_xml_start_tag(self->file, "c:doughnutChart", NULL); /* Write the c:varyColors element. */ @@ -4730,9 +5508,25 @@ _chart_write_doughnut_chart(lxw_chart *self) * Write a line chart. */ STATIC void -_chart_write_line_chart(lxw_chart *self) +_chart_write_line_chart(lxw_chart *self, uint8_t primary_axes) { lxw_chart_series *series; + uint8_t has_series = LXW_FALSE; + + /* Check if there are any series for this axis type. */ + STAILQ_FOREACH(series, self->series_list, list_pointers) { + if (primary_axes && !series->y2_axis) { + has_series = LXW_TRUE; + break; + } + if (!primary_axes && series->y2_axis) { + has_series = LXW_TRUE; + break; + } + } + + if (!has_series) + return; lxw_xml_start_tag(self->file, "c:lineChart", NULL); @@ -4740,6 +5534,11 @@ _chart_write_line_chart(lxw_chart *self) _chart_write_grouping(self, self->grouping); STAILQ_FOREACH(series, self->series_list, list_pointers) { + /* Only write series for the current axis type. */ + if (primary_axes && series->y2_axis) + continue; + if (!primary_axes && !series->y2_axis) + continue; /* Write the c:ser element. */ _chart_write_ser(self, series); } @@ -4757,19 +5556,118 @@ _chart_write_line_chart(lxw_chart *self) _chart_write_marker_value(self); /* Write the c:axId elements. */ - _chart_write_axis_ids(self); + if (primary_axes) + _chart_write_axis_ids(self); + else + _chart_write_axis_ids_2(self); lxw_xml_end_tag(self->file, "c:lineChart"); } +/* + * Write a stock chart. + */ +STATIC void +_chart_write_stock_chart(lxw_chart *self, uint8_t primary_axes) +{ + lxw_chart_series *series; + uint8_t has_series = LXW_FALSE; + uint16_t index = 0; + + /* Default line for stock chart series (width 2.25, noFill). */ + lxw_chart_line default_line = {.width = 2.25,.none = LXW_TRUE }; + + /* Default markers for stock chart series. */ + lxw_chart_marker default_marker_none = {.type = LXW_CHART_MARKER_NONE }; + lxw_chart_marker default_marker_dot = {.type = LXW_CHART_MARKER_DOT, + .size = 3 + }; + + /* Check if there are any series for this axis type. */ + STAILQ_FOREACH(series, self->series_list, list_pointers) { + if (primary_axes && !series->y2_axis) { + has_series = LXW_TRUE; + break; + } + if (!primary_axes && series->y2_axis) { + has_series = LXW_TRUE; + break; + } + } + + if (!has_series) + return; + + lxw_xml_start_tag(self->file, "c:stockChart", NULL); + + STAILQ_FOREACH(series, self->series_list, list_pointers) { + lxw_chart_line *orig_line = series->line; + lxw_chart_marker *orig_marker = series->marker; + + /* Only write series for the current axis type. */ + if (primary_axes && series->y2_axis) { + index++; + continue; + } + if (!primary_axes && !series->y2_axis) { + index++; + continue; + } + + /* Apply default line formatting if not user-defined. */ + if (!series->line) + series->line = &default_line; + + /* Apply default marker formatting if not user-defined. */ + if (!series->marker) { + /* Series 2 (index % 4 == 2) gets dot marker, others get none. */ + if (index % 4 == 2) + series->marker = &default_marker_dot; + else + series->marker = &default_marker_none; + } + + /* Write the c:ser element. */ + _chart_write_ser(self, series); + + /* Restore original values. */ + series->line = orig_line; + series->marker = orig_marker; + + index++; + } + + /* Write the c:dropLines element. */ + _chart_write_drop_lines(self); + + /* Write the c:hiLowLines element (primary axes only). */ + if (primary_axes) + _chart_write_hi_low_lines(self); + + /* Write the c:upDownBars element. */ + _chart_write_up_down_bars(self); + + /* Write the c:axId elements. */ + if (primary_axes) + _chart_write_axis_ids(self); + else + _chart_write_axis_ids_2(self); + + lxw_xml_end_tag(self->file, "c:stockChart"); +} + /* * Write a pie chart. */ STATIC void -_chart_write_pie_chart(lxw_chart *self) +_chart_write_pie_chart(lxw_chart *self, uint8_t primary_axes) { lxw_chart_series *series; + /* Pie charts don't support secondary axes. */ + if (!primary_axes) + return; + lxw_xml_start_tag(self->file, "c:pieChart", NULL); /* Write the c:varyColors element. */ @@ -4790,9 +5688,25 @@ _chart_write_pie_chart(lxw_chart *self) * Write a scatter chart. */ STATIC void -_chart_write_scatter_chart(lxw_chart *self) +_chart_write_scatter_chart(lxw_chart *self, uint8_t primary_axes) { lxw_chart_series *series; + uint8_t has_series = LXW_FALSE; + + /* Check if there are any series for this axis type. */ + STAILQ_FOREACH(series, self->series_list, list_pointers) { + if (primary_axes && !series->y2_axis) { + has_series = LXW_TRUE; + break; + } + if (!primary_axes && series->y2_axis) { + has_series = LXW_TRUE; + break; + } + } + + if (!has_series) + return; lxw_xml_start_tag(self->file, "c:scatterChart", NULL); @@ -4800,6 +5714,11 @@ _chart_write_scatter_chart(lxw_chart *self) _chart_write_scatter_style(self); STAILQ_FOREACH(series, self->series_list, list_pointers) { + /* Only write series for the current axis type. */ + if (primary_axes && series->y2_axis) + continue; + if (!primary_axes && !series->y2_axis) + continue; /* Add default scatter chart formatting to the series data unless * it has already been specified by the user.*/ @@ -4819,7 +5738,10 @@ _chart_write_scatter_chart(lxw_chart *self) } /* Write the c:axId elements. */ - _chart_write_axis_ids(self); + if (primary_axes) + _chart_write_axis_ids(self); + else + _chart_write_axis_ids_2(self); lxw_xml_end_tag(self->file, "c:scatterChart"); } @@ -4828,9 +5750,25 @@ _chart_write_scatter_chart(lxw_chart *self) * Write a radar chart. */ STATIC void -_chart_write_radar_chart(lxw_chart *self) +_chart_write_radar_chart(lxw_chart *self, uint8_t primary_axes) { lxw_chart_series *series; + uint8_t has_series = LXW_FALSE; + + /* Check if there are any series for this axis type. */ + STAILQ_FOREACH(series, self->series_list, list_pointers) { + if (primary_axes && !series->y2_axis) { + has_series = LXW_TRUE; + break; + } + if (!primary_axes && series->y2_axis) { + has_series = LXW_TRUE; + break; + } + } + + if (!has_series) + return; lxw_xml_start_tag(self->file, "c:radarChart", NULL); @@ -4838,12 +5776,20 @@ _chart_write_radar_chart(lxw_chart *self) _chart_write_radar_style(self); STAILQ_FOREACH(series, self->series_list, list_pointers) { + /* Only write series for the current axis type. */ + if (primary_axes && series->y2_axis) + continue; + if (!primary_axes && !series->y2_axis) + continue; /* Write the c:ser element. */ _chart_write_ser(self, series); } /* Write the c:axId elements. */ - _chart_write_axis_ids(self); + if (primary_axes) + _chart_write_axis_ids(self); + else + _chart_write_axis_ids_2(self); lxw_xml_end_tag(self->file, "c:radarChart"); } @@ -4873,7 +5819,32 @@ _chart_write_scatter_plot_area(lxw_chart *self) _chart_write_layout(self, self->plotarea_layout); /* Write subclass chart type elements for primary and secondary axes. */ - self->write_chart_type(self); + self->write_chart_type(self, LXW_TRUE); + self->write_chart_type(self, LXW_FALSE); + + /* Configure a combined chart if present. */ + if (self->combined) { + self->combined->id = (self->combined->is_secondary) ? + 1000 + self->id : self->id; + self->combined->file = self->file; + self->combined->series_index = self->series_index; + + /* Combined charts use the primary chart's axis IDs. */ + if (!self->combined->is_secondary) { + /* Non-secondary combined chart uses primary chart's axis IDs. */ + self->combined->axis_id_1 = self->axis_id_1; + self->combined->axis_id_2 = self->axis_id_2; + } + else { + /* Secondary combined chart uses primary chart's secondary axis IDs. */ + self->combined->axis_id_1 = self->axis_id_3; + self->combined->axis_id_2 = self->axis_id_4; + } + + /* Write the subclass chart type elements for the combined chart. */ + self->combined->write_chart_type(self->combined, LXW_TRUE); + self->combined->write_chart_type(self->combined, LXW_FALSE); + } /* Reverse the opposite axis position if crossing position is "max". */ _chart_adjust_max_crossing(self); @@ -4886,9 +5857,34 @@ _chart_write_scatter_plot_area(lxw_chart *self) /* Write the c:valAx element. */ _chart_write_val_axis(self); + /* Write the secondary axis elements. */ + _chart_write_val_axis_2(self); + + /* Write the secondary axis for the combined chart. + * Use the primary chart's y2_axis settings for axis title, formatting, etc. */ + if (self->combined && self->combined->is_secondary) { + lxw_chart_axis *combined_y2_axis = self->combined->y2_axis; + self->combined->y2_axis = self->y2_axis; + _chart_write_val_axis_2(self->combined); + self->combined->y2_axis = combined_y2_axis; + } + + _chart_write_cat_axis_2(self); + + /* Write the secondary category axis for the combined chart. + * Use the primary chart's x2_axis settings for axis formatting, etc. */ + if (self->combined && self->combined->is_secondary) { + lxw_chart_axis *combined_x2_axis = self->combined->x2_axis; + self->combined->x2_axis = self->x2_axis; + _chart_write_cat_axis_2(self->combined); + self->combined->x2_axis = combined_x2_axis; + } + /* Write the c:spPr element for the plotarea formatting. */ - _chart_write_sp_pr(self, self->plotarea_line, self->plotarea_fill, - self->plotarea_pattern); + _chart_write_sp_pr_with_gradient(self, self->plotarea_line, + self->plotarea_fill, + self->plotarea_pattern, + self->plotarea_gradient); lxw_xml_end_tag(self->file, "c:plotArea"); } @@ -4904,12 +5900,96 @@ _chart_write_pie_plot_area(lxw_chart *self) /* Write the c:layout element. */ _chart_write_layout(self, self->plotarea_layout); - /* Write subclass chart type elements for primary and secondary axes. */ - self->write_chart_type(self); + /* Write subclass chart type elements (pie/doughnut don't have secondary axes). */ + self->write_chart_type(self, LXW_TRUE); + + /* Configure a combined chart if present (pie/doughnut + pie/doughnut). */ + if (self->combined) { + self->combined->file = self->file; + self->combined->series_index = self->series_index; + + /* Write the subclass chart type elements for the combined chart. */ + self->combined->write_chart_type(self->combined, LXW_TRUE); + } /* Write the c:spPr element for the plotarea formatting. */ - _chart_write_sp_pr(self, self->plotarea_line, self->plotarea_fill, - self->plotarea_pattern); + _chart_write_sp_pr_with_gradient(self, self->plotarea_line, + self->plotarea_fill, + self->plotarea_pattern, + self->plotarea_gradient); + + lxw_xml_end_tag(self->file, "c:plotArea"); +} + +/* + * Write the element for stock charts (uses date axis). + */ +STATIC void +_chart_write_stock_plot_area(lxw_chart *self) +{ + lxw_xml_start_tag(self->file, "c:plotArea", NULL); + + /* Write the c:layout element. */ + _chart_write_layout(self, self->plotarea_layout); + + /* Write subclass chart type elements for primary and secondary axes. */ + self->write_chart_type(self, LXW_TRUE); + self->write_chart_type(self, LXW_FALSE); + + /* Configure a combined chart if present. */ + if (self->combined) { + self->combined->id = (self->combined->is_secondary) ? + 1000 + self->id : self->id; + self->combined->file = self->file; + self->combined->series_index = self->series_index; + + /* Combined charts use the primary chart's axis IDs. */ + if (!self->combined->is_secondary) { + self->combined->axis_id_1 = self->axis_id_1; + self->combined->axis_id_2 = self->axis_id_2; + } + else { + self->combined->axis_id_1 = self->axis_id_3; + self->combined->axis_id_2 = self->axis_id_4; + } + + /* Write the subclass chart type elements for the combined chart. */ + self->combined->write_chart_type(self->combined, LXW_TRUE); + self->combined->write_chart_type(self->combined, LXW_FALSE); + } + + /* Reverse the opposite axis position if crossing position is "max". */ + _chart_adjust_max_crossing(self); + + /* Write the c:dateAx element (stock charts use date axis). */ + _chart_write_date_axis(self); + + /* Write the c:valAx element. */ + _chart_write_val_axis(self); + + /* Write the secondary axis elements. */ + _chart_write_val_axis_2(self); + + /* Write the secondary axis for the combined chart. + * Use the primary chart's y2_axis settings for axis title, formatting, etc. */ + if (self->combined && self->combined->is_secondary) { + lxw_chart_axis *combined_y2_axis = self->combined->y2_axis; + self->combined->y2_axis = self->y2_axis; + _chart_write_val_axis_2(self->combined); + self->combined->y2_axis = combined_y2_axis; + } + + /* Write the secondary date axis for stock charts. */ + _chart_write_date_axis_2(self); + + /* Write the c:dTable element. */ + _chart_write_d_table(self); + + /* Write the c:spPr element for the plotarea formatting. */ + _chart_write_sp_pr_with_gradient(self, self->plotarea_line, + self->plotarea_fill, + self->plotarea_pattern, + self->plotarea_gradient); lxw_xml_end_tag(self->file, "c:plotArea"); } @@ -4926,23 +6006,76 @@ _chart_write_plot_area(lxw_chart *self) _chart_write_layout(self, self->plotarea_layout); /* Write subclass chart type elements for primary and secondary axes. */ - self->write_chart_type(self); + self->write_chart_type(self, LXW_TRUE); + self->write_chart_type(self, LXW_FALSE); + + /* Configure a combined chart if present. */ + if (self->combined) { + self->combined->id = (self->combined->is_secondary) ? + 1000 + self->id : self->id; + self->combined->file = self->file; + self->combined->series_index = self->series_index; + + /* Combined charts use the primary chart's axis IDs. */ + if (!self->combined->is_secondary) { + /* Non-secondary combined chart uses primary chart's axis IDs. */ + self->combined->axis_id_1 = self->axis_id_1; + self->combined->axis_id_2 = self->axis_id_2; + } + else { + /* Secondary combined chart uses primary chart's secondary axis IDs. */ + self->combined->axis_id_1 = self->axis_id_3; + self->combined->axis_id_2 = self->axis_id_4; + } + + /* Write the subclass chart type elements for the combined chart. */ + self->combined->write_chart_type(self->combined, LXW_TRUE); + self->combined->write_chart_type(self->combined, LXW_FALSE); + } /* Reverse the opposite axis position if crossing position is "max". */ _chart_adjust_max_crossing(self); - /* Write the c:catAx element. */ - _chart_write_cat_axis(self); + /* Write the c:catAx or c:dateAx element. */ + if (self->x_axis->is_date) + _chart_write_date_axis(self); + else + _chart_write_cat_axis(self); /* Write the c:valAx element. */ _chart_write_val_axis(self); + /* Write the secondary axis elements. */ + _chart_write_val_axis_2(self); + + /* Write the secondary axis for the combined chart. + * Use the primary chart's y2_axis settings for axis title, formatting, etc. */ + if (self->combined && self->combined->is_secondary) { + lxw_chart_axis *combined_y2_axis = self->combined->y2_axis; + self->combined->y2_axis = self->y2_axis; + _chart_write_val_axis_2(self->combined); + self->combined->y2_axis = combined_y2_axis; + } + + _chart_write_cat_axis_2(self); + + /* Write the secondary category axis for the combined chart. + * Use the primary chart's x2_axis settings for axis formatting, etc. */ + if (self->combined && self->combined->is_secondary) { + lxw_chart_axis *combined_x2_axis = self->combined->x2_axis; + self->combined->x2_axis = self->x2_axis; + _chart_write_cat_axis_2(self->combined); + self->combined->x2_axis = combined_x2_axis; + } + /* Write the c:dTable element. */ _chart_write_d_table(self); /* Write the c:spPr element for the plotarea formatting. */ - _chart_write_sp_pr(self, self->plotarea_line, self->plotarea_fill, - self->plotarea_pattern); + _chart_write_sp_pr_with_gradient(self, self->plotarea_line, + self->plotarea_fill, + self->plotarea_pattern, + self->plotarea_gradient); lxw_xml_end_tag(self->file, "c:plotArea"); } @@ -5183,6 +6316,30 @@ _chart_initialize_radar_chart(lxw_chart *self, uint8_t type) self->write_plot_area = _chart_write_plot_area; } +/* + * Initialize a stock chart. + */ +STATIC void +_chart_initialize_stock_chart(lxw_chart *self) +{ + self->chart_group = LXW_CHART_STOCK; + self->x_axis->is_category = LXW_TRUE; + self->y_axis->is_value = LXW_TRUE; + self->date_category = LXW_TRUE; + self->default_label_position = LXW_CHART_LABEL_POSITION_RIGHT; + + /* Stock charts have hi-low lines enabled by default. */ + self->has_high_low_lines = LXW_TRUE; + + /* Set default date format for the X axis. */ + _chart_axis_set_default_num_format(self->x_axis, "dd/mm/yyyy"); + _chart_axis_set_default_num_format(self->x2_axis, "dd/mm/yyyy"); + + /* Initialize the function pointers for this chart type. */ + self->write_chart_type = _chart_write_stock_chart; + self->write_plot_area = _chart_write_stock_plot_area; +} + /* * Initialize the chart specific properties. */ @@ -5237,6 +6394,10 @@ _chart_initialize(lxw_chart *self, uint8_t type) _chart_initialize_radar_chart(self, type); break; + case LXW_CHART_STOCK: + _chart_initialize_stock_chart(self); + break; + default: LXW_WARN_FORMAT1("workbook_add_chart(): " "unhandled chart type '%d'", type); @@ -5274,8 +6435,10 @@ lxw_chart_assemble_xml_file(lxw_chart *self) _chart_write_chart(self); /* Write the c:spPr element for the chartarea formatting. */ - _chart_write_sp_pr(self, self->chartarea_line, self->chartarea_fill, - self->chartarea_pattern); + _chart_write_sp_pr_with_gradient(self, self->chartarea_line, + self->chartarea_fill, + self->chartarea_pattern, + self->chartarea_gradient); /* Write the c:printSettings element. */ if (!self->is_chartsheet) @@ -5318,14 +6481,14 @@ lxw_chart_add_data_cache(lxw_series_range *range, uint8_t *data, * Add a series to the chart. */ lxw_chart_series * -chart_add_series(lxw_chart *self, const char *categories, const char *values) +chart_add_series_impl(lxw_chart *self, const char *categories, + const char *values, uint8_t y2_axis) { lxw_chart_series *series; /* Scatter charts require categories and values. */ if (self->chart_group == LXW_CHART_SCATTER && values && !categories) { - LXW_WARN("chart_add_series(): scatter charts must have " - "'categories' and 'values'"); + LXW_WARN("chart_add_series(): scatter charts must have " "'categories' and 'values'"); /* Keep user-facing name */ return NULL; } @@ -5384,6 +6547,13 @@ chart_add_series(lxw_chart *self, const char *categories, const char *values) series->default_label_position = self->default_label_position; + /* Set the secondary axis flag. */ + series->y2_axis = y2_axis; + if (y2_axis) { + self->has_secondary_axis = LXW_TRUE; + self->is_secondary = LXW_TRUE; + } + STAILQ_INSERT_TAIL(self->series_list, series, list_pointers); return series; @@ -5527,18 +6697,28 @@ chart_series_set_pattern(lxw_chart_series *series, lxw_chart_pattern *pattern) series->pattern = _chart_convert_pattern_args(pattern); } +/* + * Set a gradient fill type for a series. + */ +void +chart_series_set_gradient(lxw_chart_series *series, + lxw_chart_gradient_fill *gradient) +{ + if (!gradient) + return; + + /* Free any previously allocated resource. */ + free(series->gradient); + + series->gradient = _chart_convert_gradient_args(gradient); +} + /* * Set a marker type for a series. */ void chart_series_set_marker_type(lxw_chart_series *series, uint8_t type) { - if (type > LXW_CHART_MARKER_PLUS) { - LXW_WARN_FORMAT1 - ("chart_series_set_marker_type(): invalid marker type: %d", type); - return; - } - if (!series->marker) { lxw_chart_marker *marker = calloc(1, sizeof(struct lxw_chart_marker)); RETURN_VOID_ON_MEM_ERROR(marker); @@ -5554,13 +6734,6 @@ chart_series_set_marker_type(lxw_chart_series *series, uint8_t type) void chart_series_set_marker_size(lxw_chart_series *series, uint8_t size) { - if (size < 2 || size > 72) { - LXW_WARN_FORMAT1 - ("chart_series_set_marker_size(): marker size '%d' outside Excel range: 2 <= size <= 72", - size); - return; - } - if (!series->marker) { lxw_chart_marker *marker = calloc(1, sizeof(struct lxw_chart_marker)); RETURN_VOID_ON_MEM_ERROR(marker); @@ -5787,13 +6960,6 @@ mem_error: void chart_series_set_labels_separator(lxw_chart_series *series, uint8_t separator) { - if (separator > LXW_CHART_LABEL_SEPARATOR_SPACE) { - LXW_WARN_FORMAT1 - ("chart_series_set_labels_separator(): invalid label separator: %d", - separator); - return; - } - series->has_labels = LXW_TRUE; series->label_separator = separator; } @@ -5804,13 +6970,6 @@ chart_series_set_labels_separator(lxw_chart_series *series, uint8_t separator) void chart_series_set_labels_position(lxw_chart_series *series, uint8_t position) { - if (position > LXW_CHART_LABEL_POSITION_BEST_FIT) { - LXW_WARN_FORMAT1 - ("chart_series_set_labels_position(): invalid label position: %d", - position); - return; - } - series->has_labels = LXW_TRUE; series->show_labels_value = LXW_TRUE; @@ -5932,13 +7091,6 @@ void chart_series_set_trendline(lxw_chart_series *series, uint8_t type, uint8_t value) { - if (type > LXW_CHART_TRENDLINE_TYPE_AVERAGE) { - LXW_WARN_FORMAT1 - ("chart_series_set_trendline(): invalid trendline type: %d", - type); - return; - } - if (type == LXW_CHART_TRENDLINE_TYPE_POLY || type == LXW_CHART_TRENDLINE_TYPE_AVERAGE) { @@ -6162,6 +7314,18 @@ chart_series_set_error_bars_line(lxw_series_error_bars *error_bars, error_bars->line = _chart_convert_line_args(line); } +/* + * Combine two charts into a single combined chart. + */ +void +chart_combine(lxw_chart *self, lxw_chart *combined_chart) +{ + if (!self || !combined_chart) + return; + + self->combined = combined_chart; +} + /* * Get an axis pointer from a chart. */ @@ -6175,6 +7339,10 @@ chart_axis_get(lxw_chart *self, lxw_chart_axis_type axis_type) return self->x_axis; else if (axis_type == LXW_CHART_AXIS_TYPE_Y) return self->y_axis; + else if (axis_type == LXW_CHART_AXIS_TYPE_X2) + return self->x2_axis; + else if (axis_type == LXW_CHART_AXIS_TYPE_Y2) + return self->y2_axis; else return NULL; } @@ -6370,12 +7538,6 @@ chart_axis_off(lxw_chart_axis *axis) void chart_axis_set_position(lxw_chart_axis *axis, uint8_t position) { - if (position > LXW_CHART_AXIS_POSITION_BETWEEN) { - LXW_WARN_FORMAT1 - ("chart_axis_set_position(): invalid position: %d", position); - return; - } - LXW_WARN_CAT_AND_DATE_AXIS_ONLY("chart_axis_set_position"); axis->position_axis = position; @@ -6387,13 +7549,6 @@ chart_axis_set_position(lxw_chart_axis *axis, uint8_t position) void chart_axis_set_label_position(lxw_chart_axis *axis, uint8_t position) { - if (position > LXW_CHART_AXIS_LABEL_POSITION_NONE) { - LXW_WARN_FORMAT1 - ("chart_axis_set_label_position(): invalid label position: %d", - position); - return; - } - axis->label_position = position; } @@ -6440,13 +7595,6 @@ chart_axis_set_log_base(lxw_chart_axis *axis, uint16_t log_base) void chart_axis_set_major_tick_mark(lxw_chart_axis *axis, uint8_t type) { - if (type > LXW_CHART_AXIS_TICK_MARK_CROSSING) { - LXW_WARN_FORMAT1 - ("chart_axis_set_major_tick_mark(): invalid tick mark type: %d", - type); - return; - } - axis->major_tick_mark = type; } @@ -6456,13 +7604,6 @@ chart_axis_set_major_tick_mark(lxw_chart_axis *axis, uint8_t type) void chart_axis_set_minor_tick_mark(lxw_chart_axis *axis, uint8_t type) { - if (type > LXW_CHART_AXIS_TICK_MARK_CROSSING) { - LXW_WARN_FORMAT1 - ("chart_axis_set_minor_tick_mark(): invalid tick mark type: %d", - type); - return; - } - axis->minor_tick_mark = type; } @@ -6512,19 +7653,41 @@ chart_axis_set_minor_unit(lxw_chart_axis *axis, double unit) axis->minor_unit = unit; } +/* + * Set the category axis as a date axis. + */ +void +chart_axis_set_date_axis(lxw_chart_axis *axis) +{ + LXW_WARN_CAT_AXIS_ONLY("chart_axis_set_date_axis"); + + axis->is_date = LXW_TRUE; +} + +/* + * Set the time unit type for the major unit of a date axis. + */ +void +chart_axis_set_major_unit_type(lxw_chart_axis *axis, uint8_t type) +{ + axis->major_unit_type = type; +} + +/* + * Set the time unit type for the minor unit of a date axis. + */ +void +chart_axis_set_minor_unit_type(lxw_chart_axis *axis, uint8_t type) +{ + axis->minor_unit_type = type; +} + /* * Set the display units for a value axis. */ void chart_axis_set_display_units(lxw_chart_axis *axis, uint8_t units) { - if (units > LXW_CHART_AXIS_UNITS_TRILLIONS) { - LXW_WARN_FORMAT1 - ("chart_axis_set_display_units(): invalid display units: %d", - units); - return; - } - LXW_WARN_VALUE_AXIS_ONLY("chart_axis_set_display_units"); axis->display_units = units; @@ -6606,13 +7769,6 @@ chart_axis_minor_gridlines_set_line(lxw_chart_axis *axis, void chart_axis_set_label_align(lxw_chart_axis *axis, uint8_t align) { - if (align > LXW_CHART_AXIS_LABEL_ALIGN_RIGHT) { - LXW_WARN_FORMAT1 - ("chart_axis_set_label_align(): invalid label alignment: %d", - align); - return; - } - axis->label_align = align; } @@ -6699,13 +7855,6 @@ chart_title_set_overlay(lxw_chart *self, uint8_t overlay) void chart_legend_set_position(lxw_chart *self, uint8_t position) { - if (position > LXW_CHART_LEGEND_OVERLAY_TOP_RIGHT) { - LXW_WARN_FORMAT1 - ("chart_legend_set_position(): invalid legend position: %d", - position); - return; - } - self->legend.position = position; } @@ -6811,6 +7960,22 @@ chart_chartarea_set_pattern(lxw_chart *self, lxw_chart_pattern *pattern) self->chartarea_pattern = _chart_convert_pattern_args(pattern); } +/* + * Set a gradient fill type for the chartarea. + */ +void +chart_chartarea_set_gradient(lxw_chart *self, + lxw_chart_gradient_fill *gradient) +{ + if (!gradient) + return; + + /* Free any previously allocated resource. */ + free(self->chartarea_gradient); + + self->chartarea_gradient = _chart_convert_gradient_args(gradient); +} + /* * Set a line type for the plotarea. */ @@ -6856,6 +8021,22 @@ chart_plotarea_set_pattern(lxw_chart *self, lxw_chart_pattern *pattern) self->plotarea_pattern = _chart_convert_pattern_args(pattern); } +/* + * Set a gradient fill type for the plotarea. + */ +void +chart_plotarea_set_gradient(lxw_chart *self, + lxw_chart_gradient_fill *gradient) +{ + if (!gradient) + return; + + /* Free any previously allocated resource. */ + free(self->plotarea_gradient); + + self->plotarea_gradient = _chart_convert_gradient_args(gradient); +} + /* * Set a layout for the plotarea. */ @@ -6992,13 +8173,6 @@ chart_set_series_overlap(lxw_chart *self, int8_t overlap) void chart_show_blanks_as(lxw_chart *self, uint8_t option) { - if (option > LXW_CHART_BLANKS_AS_CONNECTED) { - LXW_WARN_FORMAT1 - ("chart_show_blanks_as(): invalid blank display option: %d", - option); - return; - } - self->show_blanks_as = option; } @@ -7024,6 +8198,33 @@ chart_set_series_gap(lxw_chart *self, uint16_t gap) "outside Excel range: 0 <= gap <= 500", gap); } +/* + * Set the Bar/Column overlap for secondary axis data series. + */ +void +chart_set_series_overlap_y2(lxw_chart *self, int8_t overlap) +{ + if (overlap >= -100 && overlap <= 100) + self->overlap_y2 = overlap; + else + LXW_WARN_FORMAT1 + ("chart_set_series_overlap_y2(): Chart series overlap " + "'%d' outside Excel range: -100 <= overlap <= 100", overlap); +} + +/* + * Set the Bar/Column gap for secondary axis data series. + */ +void +chart_set_series_gap_y2(lxw_chart *self, uint16_t gap) +{ + if (gap <= 500) + self->gap_y2 = gap; + else + LXW_WARN_FORMAT1("chart_set_series_gap_y2(): Chart series gap '%d' " + "outside Excel range: 0 <= gap <= 500", gap); +} + /* * Set the Pie/Doughnut chart rotation: the angle of the first slice. */ diff --git a/src/content_types.c b/src/content_types.c index 830be522..0b6c888d 100644 --- a/src/content_types.c +++ b/src/content_types.c @@ -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"); +} diff --git a/src/drawing.c b/src/drawing.c index 8371873f..061e6190 100644 --- a/src/drawing.c +++ b/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,325 @@ _drawing_write_pic(lxw_drawing *self, uint32_t index, lxw_xml_end_tag(self->file, "xdr:pic"); } +/* + * Write the 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 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 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 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 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 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 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 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 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 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 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 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 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 element. */ @@ -842,10 +1162,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. */ diff --git a/src/feature_property_bag.c b/src/feature_property_bag.c new file mode 100644 index 00000000..5a70e5ec --- /dev/null +++ b/src/feature_property_bag.c @@ -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 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 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 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 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 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 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 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"); +} diff --git a/src/format.c b/src/format.c index dde2fd86..dea02ac0 100644 --- a/src/format.c +++ b/src/format.c @@ -101,6 +101,8 @@ lxw_format_new(void) format->quote_prefix = LXW_FALSE; + format->checkbox = LXW_FALSE; + return format; mem_error: @@ -546,12 +548,6 @@ format_set_text_justlast(lxw_format *self) void format_set_pattern(lxw_format *self, uint8_t value) { - if (value > LXW_PATTERN_GRAY_0625) { - LXW_WARN_FORMAT1("format_set_pattern(): invalid pattern value: %d", - value); - return; - } - self->pattern = value; } @@ -695,12 +691,6 @@ format_set_diag_color(lxw_format *self, lxw_color_t color) void format_set_diag_border(lxw_format *self, uint8_t style) { - if (style > LXW_BORDER_SLANT_DASH_DOT) { - LXW_WARN_FORMAT1("format_set_diag_border(): invalid border style: %d", - style); - return; - } - self->diag_border = style; } @@ -719,13 +709,6 @@ format_set_num_format_index(lxw_format *self, uint8_t value) void format_set_valign(lxw_format *self, uint8_t value) { - if (value > LXW_ALIGN_VERTICAL_DISTRIBUTED) { - LXW_WARN_FORMAT1 - ("format_set_valign(): invalid vertical alignment value: %d", - value); - return; - } - self->text_v_align = value; } @@ -830,3 +813,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; +} diff --git a/src/labview_wrappers.c b/src/labview_wrappers.c new file mode 100644 index 00000000..cb47538d --- /dev/null +++ b/src/labview_wrappers.c @@ -0,0 +1,703 @@ +/* + * 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 +#include +#include + +/* 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 +#include + +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; +} diff --git a/src/packager.c b/src/packager.c index 4654bf63..41b2b894 100644 --- a/src/packager.c +++ b/src/packager.c @@ -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); diff --git a/src/relationships.c b/src/relationships.c index 4b7149cf..e062c3ca 100644 --- a/src/relationships.c +++ b/src/relationships.c @@ -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); +} diff --git a/src/styles.c b/src/styles.c index cbfcaa8b..4fe04252 100644 --- a/src/styles.c +++ b/src/styles.c @@ -1187,6 +1187,34 @@ _write_protection(lxw_styles *self, lxw_format *format) LXW_FREE_ATTRIBUTES(); } +/* + * Write the xfComplement 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 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 { diff --git a/src/utility.c b/src/utility.c index 012474e0..a88425a5 100644 --- a/src/utility.c +++ b/src/utility.c @@ -41,7 +41,6 @@ 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.", "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,69 +332,6 @@ lxw_name_to_col_2(const char *col_str) return 0; } -lxw_error -lxw_datetime_validate(lxw_datetime *datetime) -{ - if (!datetime) - return LXW_ERROR_DATETIME_VALIDATION; - - /* - * Excel uses the year 1900 as the default epoch but it uses 1899-12-31 as - * the 0 date and internally we use the 0-0-0 date for time only values. - */ - if (datetime->year < 1900 && - !(datetime->year == 0 && - datetime->month == 0 && datetime->day == 0) && - !(datetime->year == 1899 && - datetime->month == 12 && datetime->day == 31)) { - - LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid year: %d. " - "Valid range is 1900-9999.", datetime->year); - - return LXW_ERROR_DATETIME_VALIDATION; - } - - if (datetime->year > 9999) { - LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid year: %d. " - "Valid range is 1900-9999.", datetime->year); - return LXW_ERROR_DATETIME_VALIDATION; - } - - if (datetime->year != 0) { - if (datetime->month < 1 || datetime->month > 12) { - LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid month: %d. " - "Valid range is 1-12.", datetime->month); - return LXW_ERROR_DATETIME_VALIDATION; - } - - if (datetime->day < 1 || datetime->day > 31) { - LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid day: %d. " - "Valid range is 1-31.", datetime->day); - return LXW_ERROR_DATETIME_VALIDATION; - } - } - - if (datetime->hour < 0 || datetime->hour > 23) { - LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid hour: %d. " - "Valid range is 0-23.", datetime->hour); - return LXW_ERROR_DATETIME_VALIDATION; - } - - if (datetime->min < 0 || datetime->min > 59) { - LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid minute: %d. " - "Valid range is 0-59.", datetime->min); - return LXW_ERROR_DATETIME_VALIDATION; - } - - if (datetime->sec < 0.0 || datetime->sec >= 60.0) { - LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid seconds: %.3f. " - "Valid range is 0.0-59.999.", datetime->sec); - return LXW_ERROR_DATETIME_VALIDATION; - } - - return LXW_NO_ERROR; -} - /* * Convert a lxw_datetime struct to an Excel serial date, with a 1900 * or 1904 epoch. @@ -421,9 +357,6 @@ lxw_datetime_to_excel_date_with_epoch(lxw_datetime *datetime, int days = 0; int i; - if (lxw_datetime_validate(datetime) != LXW_NO_ERROR) - return 0.0; - /* For times without dates set the default date for the epoch. */ if (!year) { if (!use_1904_epoch) { @@ -749,6 +682,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 diff --git a/src/workbook.c b/src/workbook.c index d31b1bf9..3caf0fad 100644 --- a/src/workbook.c +++ b/src/workbook.c @@ -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,12 @@ _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 +2001,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 +2078,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,12 +2207,6 @@ workbook_add_chart(lxw_workbook *self, uint8_t type) { lxw_chart *chart; - if (type == LXW_CHART_NONE || type > LXW_CHART_RADAR_FILLED) { - LXW_WARN_FORMAT1("workbook_add_chart(): invalid chart type: %d", - type); - return NULL; - } - /* Create a new chart object. */ chart = lxw_chart_new(type); @@ -2247,6 +2281,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. */ @@ -2660,10 +2697,6 @@ workbook_set_custom_property_datetime(lxw_workbook *self, const char *name, return LXW_ERROR_NULL_PARAMETER_IGNORED; } - if (lxw_datetime_validate(datetime) != LXW_NO_ERROR) { - return LXW_ERROR_DATETIME_VALIDATION; - } - /* Create a struct to hold the custom property. */ custom_property = calloc(1, sizeof(struct lxw_custom_property)); RETURN_ON_MEM_ERROR(custom_property, LXW_ERROR_MEMORY_MALLOC_FAILED); diff --git a/src/worksheet.c b/src/worksheet.c index 7fe438b4..f3ce0617 100644 --- a/src/worksheet.c +++ b/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,218 @@ _worksheet_write_conditional_formatting_2010(lxw_worksheet *self, lxw_cond_forma LXW_FREE_ATTRIBUTES(); } +/* + * Write a sparkline color element like . + * 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 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 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 element for Excel 2010 conditional formatting data bars. */ @@ -7187,12 +7508,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 +8642,30 @@ 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,104 @@ 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 +10242,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 +11580,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. diff --git a/test/functional/src/test_autofit01.c b/test/functional/src/test_autofit01.c new file mode 100644 index 00000000..43a45f31 --- /dev/null +++ b/test/functional/src/test_autofit01.c @@ -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); +} diff --git a/test/functional/src/test_chart_area01.c b/test/functional/src/test_chart_area01.c index f9e7efc4..d7d5c77e 100644 --- a/test/functional/src/test_chart_area01.c +++ b/test/functional/src/test_chart_area01.c @@ -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); diff --git a/test/functional/src/test_chart_area02.c b/test/functional/src/test_chart_area02.c index a593da04..bd4fb555 100644 --- a/test/functional/src/test_chart_area02.c +++ b/test/functional/src/test_chart_area02.c @@ -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); diff --git a/test/functional/src/test_chart_area03.c b/test/functional/src/test_chart_area03.c index 1fa76dde..dcd38aa3 100644 --- a/test/functional/src/test_chart_area03.c +++ b/test/functional/src/test_chart_area03.c @@ -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); diff --git a/test/functional/src/test_chart_area04.c b/test/functional/src/test_chart_area04.c new file mode 100644 index 00000000..a79ca289 --- /dev/null +++ b/test/functional/src/test_chart_area04.c @@ -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); +} diff --git a/test/functional/src/test_chart_area05.c b/test/functional/src/test_chart_area05.c index 4a5f63be..d94256f7 100644 --- a/test/functional/src/test_chart_area05.c +++ b/test/functional/src/test_chart_area05.c @@ -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); diff --git a/test/functional/src/test_chart_area06.c b/test/functional/src/test_chart_area06.c index bffd3f8b..2fda46b0 100644 --- a/test/functional/src/test_chart_area06.c +++ b/test/functional/src/test_chart_area06.c @@ -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); diff --git a/test/functional/src/test_chart_axis01.c b/test/functional/src/test_chart_axis01.c index e4537f90..75a1b785 100644 --- a/test/functional/src/test_chart_axis01.c +++ b/test/functional/src/test_chart_axis01.c @@ -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"); diff --git a/test/functional/src/test_chart_axis02.c b/test/functional/src/test_chart_axis02.c index 2cae4ba3..1dd0fce2 100644 --- a/test/functional/src/test_chart_axis02.c +++ b/test/functional/src/test_chart_axis02.c @@ -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"); diff --git a/test/functional/src/test_chart_axis04.c b/test/functional/src/test_chart_axis04.c index 5c3454fb..5384199e 100644 --- a/test/functional/src/test_chart_axis04.c +++ b/test/functional/src/test_chart_axis04.c @@ -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"); diff --git a/test/functional/src/test_chart_axis05.c b/test/functional/src/test_chart_axis05.c index a29c2d6b..4fb74c37 100644 --- a/test/functional/src/test_chart_axis05.c +++ b/test/functional/src/test_chart_axis05.c @@ -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"); diff --git a/test/functional/src/test_chart_axis06.c b/test/functional/src/test_chart_axis06.c index bffcd74d..ba31da9a 100644 --- a/test/functional/src/test_chart_axis06.c +++ b/test/functional/src/test_chart_axis06.c @@ -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"); diff --git a/test/functional/src/test_chart_axis07.c b/test/functional/src/test_chart_axis07.c index cfce9d83..33fad024 100644 --- a/test/functional/src/test_chart_axis07.c +++ b/test/functional/src/test_chart_axis07.c @@ -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"); diff --git a/test/functional/src/test_chart_axis08.c b/test/functional/src/test_chart_axis08.c index a58ac764..fbdf04a6 100644 --- a/test/functional/src/test_chart_axis08.c +++ b/test/functional/src/test_chart_axis08.c @@ -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); diff --git a/test/functional/src/test_chart_axis09.c b/test/functional/src/test_chart_axis09.c index 5af25e30..ba17b535 100644 --- a/test/functional/src/test_chart_axis09.c +++ b/test/functional/src/test_chart_axis09.c @@ -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); diff --git a/test/functional/src/test_chart_axis10.c b/test/functional/src/test_chart_axis10.c index 8d849497..7dff8ad0 100644 --- a/test/functional/src/test_chart_axis10.c +++ b/test/functional/src/test_chart_axis10.c @@ -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); diff --git a/test/functional/src/test_chart_axis11.c b/test/functional/src/test_chart_axis11.c index d43bf875..f79898b6 100644 --- a/test/functional/src/test_chart_axis11.c +++ b/test/functional/src/test_chart_axis11.c @@ -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); diff --git a/test/functional/src/test_chart_axis12.c b/test/functional/src/test_chart_axis12.c index cbcd72ee..9955d3bb 100644 --- a/test/functional/src/test_chart_axis12.c +++ b/test/functional/src/test_chart_axis12.c @@ -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); diff --git a/test/functional/src/test_chart_axis13.c b/test/functional/src/test_chart_axis13.c index d8bc1a88..39c22404 100644 --- a/test/functional/src/test_chart_axis13.c +++ b/test/functional/src/test_chart_axis13.c @@ -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); diff --git a/test/functional/src/test_chart_axis15.c b/test/functional/src/test_chart_axis15.c index d3d2c2c8..dd0d5064 100644 --- a/test/functional/src/test_chart_axis15.c +++ b/test/functional/src/test_chart_axis15.c @@ -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); diff --git a/test/functional/src/test_chart_axis17.c b/test/functional/src/test_chart_axis17.c index 56d7a2ec..e4b63921 100644 --- a/test/functional/src/test_chart_axis17.c +++ b/test/functional/src/test_chart_axis17.c @@ -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); diff --git a/test/functional/src/test_chart_axis18.c b/test/functional/src/test_chart_axis18.c index e63a10c0..b784c4b5 100644 --- a/test/functional/src/test_chart_axis18.c +++ b/test/functional/src/test_chart_axis18.c @@ -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); diff --git a/test/functional/src/test_chart_axis19.c b/test/functional/src/test_chart_axis19.c index 1dd0f4ec..6a393541 100644 --- a/test/functional/src/test_chart_axis19.c +++ b/test/functional/src/test_chart_axis19.c @@ -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); diff --git a/test/functional/src/test_chart_axis20.c b/test/functional/src/test_chart_axis20.c index 1d3106b2..8618fe40 100644 --- a/test/functional/src/test_chart_axis20.c +++ b/test/functional/src/test_chart_axis20.c @@ -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); diff --git a/test/functional/src/test_chart_axis21.c b/test/functional/src/test_chart_axis21.c index 4e3b30b6..c4070ebc 100644 --- a/test/functional/src/test_chart_axis21.c +++ b/test/functional/src/test_chart_axis21.c @@ -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); diff --git a/test/functional/src/test_chart_axis22.c b/test/functional/src/test_chart_axis22.c index 5a58b0dd..311d2579 100644 --- a/test/functional/src/test_chart_axis22.c +++ b/test/functional/src/test_chart_axis22.c @@ -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"); diff --git a/test/functional/src/test_chart_axis23.c b/test/functional/src/test_chart_axis23.c index 2bfc9e7b..47d14593 100644 --- a/test/functional/src/test_chart_axis23.c +++ b/test/functional/src/test_chart_axis23.c @@ -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%"); diff --git a/test/functional/src/test_chart_axis24.c b/test/functional/src/test_chart_axis24.c index aa0eaeb9..0c2580df 100644 --- a/test/functional/src/test_chart_axis24.c +++ b/test/functional/src/test_chart_axis24.c @@ -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%"); diff --git a/test/functional/src/test_chart_axis25.c b/test/functional/src/test_chart_axis25.c index 740a6072..9a3f22e7 100644 --- a/test/functional/src/test_chart_axis25.c +++ b/test/functional/src/test_chart_axis25.c @@ -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%"); diff --git a/test/functional/src/test_chart_axis26.c b/test/functional/src/test_chart_axis26.c index f4ee911a..08d5707c 100644 --- a/test/functional/src/test_chart_axis26.c +++ b/test/functional/src/test_chart_axis26.c @@ -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); diff --git a/test/functional/src/test_chart_axis27.c b/test/functional/src/test_chart_axis27.c index 13441c34..9b3e03e5 100644 --- a/test/functional/src/test_chart_axis27.c +++ b/test/functional/src/test_chart_axis27.c @@ -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); diff --git a/test/functional/src/test_chart_axis28.c b/test/functional/src/test_chart_axis28.c index 0595d5ef..4f05598e 100644 --- a/test/functional/src/test_chart_axis28.c +++ b/test/functional/src/test_chart_axis28.c @@ -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); diff --git a/test/functional/src/test_chart_axis29.c b/test/functional/src/test_chart_axis29.c index 6b433743..39cc1c15 100644 --- a/test/functional/src/test_chart_axis29.c +++ b/test/functional/src/test_chart_axis29.c @@ -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); diff --git a/test/functional/src/test_chart_axis30.c b/test/functional/src/test_chart_axis30.c index c4ea8214..85d7db78 100644 --- a/test/functional/src/test_chart_axis30.c +++ b/test/functional/src/test_chart_axis30.c @@ -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); diff --git a/test/functional/src/test_chart_axis31.c b/test/functional/src/test_chart_axis31.c index c0ef40e2..66aa5f53 100644 --- a/test/functional/src/test_chart_axis31.c +++ b/test/functional/src/test_chart_axis31.c @@ -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); diff --git a/test/functional/src/test_chart_axis32.c b/test/functional/src/test_chart_axis32.c index 44937de1..c8d07a62 100644 --- a/test/functional/src/test_chart_axis32.c +++ b/test/functional/src/test_chart_axis32.c @@ -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); diff --git a/test/functional/src/test_chart_axis33.c b/test/functional/src/test_chart_axis33.c index 52daa993..691f60cb 100644 --- a/test/functional/src/test_chart_axis33.c +++ b/test/functional/src/test_chart_axis33.c @@ -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}; diff --git a/test/functional/src/test_chart_axis34.c b/test/functional/src/test_chart_axis34.c index a6d36e02..8cffdcf4 100644 --- a/test/functional/src/test_chart_axis34.c +++ b/test/functional/src/test_chart_axis34.c @@ -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); diff --git a/test/functional/src/test_chart_axis35.c b/test/functional/src/test_chart_axis35.c index d33568a0..5c2edc8f 100644 --- a/test/functional/src/test_chart_axis35.c +++ b/test/functional/src/test_chart_axis35.c @@ -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_line line = {.none = LXW_TRUE}; diff --git a/test/functional/src/test_chart_axis36.c b/test/functional/src/test_chart_axis36.c index b1ab2abf..28a6ef1d 100644 --- a/test/functional/src/test_chart_axis36.c +++ b/test/functional/src/test_chart_axis36.c @@ -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_line line = {.none = LXW_TRUE}; diff --git a/test/functional/src/test_chart_axis37.c b/test/functional/src/test_chart_axis37.c index d699a427..b0854938 100644 --- a/test/functional/src/test_chart_axis37.c +++ b/test/functional/src/test_chart_axis37.c @@ -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_line line1 = {.color = LXW_COLOR_YELLOW}; lxw_chart_line line2 = {.color = LXW_COLOR_RED}; diff --git a/test/functional/src/test_chart_axis38.c b/test/functional/src/test_chart_axis38.c index a206663f..1051b1d5 100644 --- a/test/functional/src/test_chart_axis38.c +++ b/test/functional/src/test_chart_axis38.c @@ -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_line line = {.color = LXW_COLOR_YELLOW}; lxw_chart_fill fill = {.color = LXW_COLOR_RED}; diff --git a/test/functional/src/test_chart_axis39.c b/test/functional/src/test_chart_axis39.c index f1f3da21..29a34eb3 100644 --- a/test/functional/src/test_chart_axis39.c +++ b/test/functional/src/test_chart_axis39.c @@ -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_line line = {.none = LXW_TRUE}; diff --git a/test/functional/src/test_chart_axis40.c b/test/functional/src/test_chart_axis40.c index 79451415..e9b2fe72 100644 --- a/test/functional/src/test_chart_axis40.c +++ b/test/functional/src/test_chart_axis40.c @@ -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, 3); chart_axis_set_interval_tick(chart->x_axis, 2); diff --git a/test/functional/src/test_chart_axis41.c b/test/functional/src/test_chart_axis41.c index 54c86cd1..3b0eb556 100644 --- a/test/functional/src/test_chart_axis41.c +++ b/test/functional/src/test_chart_axis41.c @@ -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_tick_mark(chart->x_axis, LXW_CHART_AXIS_TICK_MARK_NONE); chart_axis_set_minor_tick_mark(chart->x_axis, LXW_CHART_AXIS_TICK_MARK_INSIDE); diff --git a/test/functional/src/test_chart_axis42.c b/test/functional/src/test_chart_axis42.c index 1753bc72..090c9dac 100644 --- a/test/functional/src/test_chart_axis42.c +++ b/test/functional/src/test_chart_axis42.c @@ -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_align(chart->x_axis, LXW_CHART_AXIS_LABEL_ALIGN_RIGHT); diff --git a/test/functional/src/test_chart_axis43.c b/test/functional/src/test_chart_axis43.c index b0ab19cb..244b7a2e 100644 --- a/test/functional/src/test_chart_axis43.c +++ b/test/functional/src/test_chart_axis43.c @@ -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_align(chart->x_axis, LXW_CHART_AXIS_LABEL_ALIGN_LEFT); diff --git a/test/functional/src/test_chart_axis44.c b/test/functional/src/test_chart_axis44.c index 31727b33..b9e0c3dd 100644 --- a/test/functional/src/test_chart_axis44.c +++ b/test/functional/src/test_chart_axis44.c @@ -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"); diff --git a/test/functional/src/test_chart_axis45.c b/test/functional/src/test_chart_axis45.c index 6d14401c..b6fda5d9 100644 --- a/test/functional/src/test_chart_axis45.c +++ b/test/functional/src/test_chart_axis45.c @@ -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"); diff --git a/test/functional/src/test_chart_axis46.c b/test/functional/src/test_chart_axis46.c index 593513ed..e419b3bb 100644 --- a/test/functional/src/test_chart_axis46.c +++ b/test/functional/src/test_chart_axis46.c @@ -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"); diff --git a/test/functional/src/test_chart_axis47.c b/test/functional/src/test_chart_axis47.c index 3e8e0443..56bd3ee6 100644 --- a/test/functional/src/test_chart_axis47.c +++ b/test/functional/src/test_chart_axis47.c @@ -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 = 360, .baseline = -1}; diff --git a/test/functional/src/test_chart_axis48.c b/test/functional/src/test_chart_axis48.c index 5093ab9f..59bd19f3 100644 --- a/test/functional/src/test_chart_axis48.c +++ b/test/functional/src/test_chart_axis48.c @@ -35,9 +35,9 @@ int main() { worksheet_write_string(worksheet, CELL("D1"), "Foo" , 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 = 360, .baseline = -1}; diff --git a/test/functional/src/test_chart_bar01.c b/test/functional/src/test_chart_bar01.c index 794376fb..5b417edf 100644 --- a/test/functional/src/test_chart_bar01.c +++ b/test/functional/src/test_chart_bar01.c @@ -33,8 +33,8 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col] , NULL); - chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5"); + 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); diff --git a/test/functional/src/test_chart_bar02.c b/test/functional/src/test_chart_bar02.c index f2b2efb3..c8d90c7c 100644 --- a/test/functional/src/test_chart_bar02.c +++ b/test/functional/src/test_chart_bar02.c @@ -36,8 +36,8 @@ int main() { worksheet_write_string(worksheet1, CELL("A1"), "Foo" , NULL); - chart_add_series(chart, "Sheet2!$A$1:$A$5", "Sheet2!$B$1:$B$5"); - chart_add_series(chart, "Sheet2!$A$1:$A$5", "Sheet2!$C$1:$C$5"); + chart_add_series(chart, "Sheet2!$A$1:$A$5", "Sheet2!$B$1:$B$5", 0); + chart_add_series(chart, "Sheet2!$A$1:$A$5", "Sheet2!$C$1:$C$5", 0); worksheet_insert_chart(worksheet2, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_bar03.c b/test/functional/src/test_chart_bar03.c index ac53c1cc..7c917eb5 100644 --- a/test/functional/src/test_chart_bar03.c +++ b/test/functional/src/test_chart_bar03.c @@ -40,24 +40,24 @@ int main() { chart_add_series(chart1, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); chart_add_series(chart1, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); worksheet_insert_chart(worksheet, CELL("E9"), chart1); chart_add_series(chart2, "=Sheet1!$A$1:$A$4", "=Sheet1!$B$1:$B$4" - ); + , 0); chart_add_series(chart2, "=Sheet1!$A$1:$A$4", "=Sheet1!$C$1:$C$4" - ); + , 0); worksheet_insert_chart(worksheet, CELL("F25"), chart2); diff --git a/test/functional/src/test_chart_bar04.c b/test/functional/src/test_chart_bar04.c index 4c328cc0..14327f2e 100644 --- a/test/functional/src/test_chart_bar04.c +++ b/test/functional/src/test_chart_bar04.c @@ -44,12 +44,12 @@ int main() { chart_add_series(chart1, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); chart_add_series(chart1, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); worksheet_insert_chart(worksheet1, CELL("E9"), chart1); @@ -57,12 +57,12 @@ int main() { chart_add_series(chart2, "=Sheet2!$A$1:$A$5", "=Sheet2!$B$1:$B$5" - ); + , 0); chart_add_series(chart2, "=Sheet2!$A$1:$A$5", "=Sheet2!$C$1:$C$5" - ); + , 0); worksheet_insert_chart(worksheet2, CELL("E9"), chart2); diff --git a/test/functional/src/test_chart_bar05.c b/test/functional/src/test_chart_bar05.c index defc490d..ef6febe5 100644 --- a/test/functional/src/test_chart_bar05.c +++ b/test/functional/src/test_chart_bar05.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_bar06.c b/test/functional/src/test_chart_bar06.c index 93ff9958..629314bc 100644 --- a/test/functional/src/test_chart_bar06.c +++ b/test/functional/src/test_chart_bar06.c @@ -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, "Apple"); chart_axis_set_name(chart->y_axis, "Pear"); diff --git a/test/functional/src/test_chart_bar08.c b/test/functional/src/test_chart_bar08.c index ed6e2431..77e95eaa 100644 --- a/test/functional/src/test_chart_bar08.c +++ b/test/functional/src/test_chart_bar08.c @@ -37,9 +37,9 @@ int main() { worksheet_write_url(worksheet, CELL("A7"), "http://www.perl.com/" , 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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_bar09.c b/test/functional/src/test_chart_bar09.c index dd5f4c1b..33831528 100644 --- a/test/functional/src/test_chart_bar09.c +++ b/test/functional/src/test_chart_bar09.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_bar10.c b/test/functional/src/test_chart_bar10.c index af991c4c..14c4b311 100644 --- a/test/functional/src/test_chart_bar10.c +++ b/test/functional/src/test_chart_bar10.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_bar11.c b/test/functional/src/test_chart_bar11.c index 17525ac0..cff5a46d 100644 --- a/test/functional/src/test_chart_bar11.c +++ b/test/functional/src/test_chart_bar11.c @@ -46,14 +46,14 @@ int main() { worksheet_write_url(worksheet, CELL("A8"), "http://www.perl.org/", NULL); worksheet_write_url(worksheet, CELL("A9"), "http://www.perl.net/", NULL); - chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5"); - chart_add_series(chart1, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart1, NULL, "=Sheet1!$C$1:$C$5"); + chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5", 0); + chart_add_series(chart1, NULL, "=Sheet1!$B$1:$B$5", 0); + chart_add_series(chart1, NULL, "=Sheet1!$C$1:$C$5", 0); - chart_add_series(chart2, NULL, "=Sheet1!$A$1:$A$5"); - chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart2, NULL, "=Sheet1!$A$1:$A$5", 0); + chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5", 0); - chart_add_series(chart3, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart3, NULL, "=Sheet1!$A$1:$A$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart1); worksheet_insert_chart(worksheet, CELL("D25"), chart2); diff --git a/test/functional/src/test_chart_bar12.c b/test/functional/src/test_chart_bar12.c index 5bbc6087..9872f776 100644 --- a/test/functional/src/test_chart_bar12.c +++ b/test/functional/src/test_chart_bar12.c @@ -34,9 +34,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); chartsheet_set_chart(chartsheet, chart); diff --git a/test/functional/src/test_chart_bar13.c b/test/functional/src/test_chart_bar13.c index 6e8c4515..19129148 100644 --- a/test/functional/src/test_chart_bar13.c +++ b/test/functional/src/test_chart_bar13.c @@ -46,13 +46,13 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet1, row, col, data[row][col], NULL); - chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5"); - chart_add_series(chart1, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart1, NULL, "=Sheet1!$C$1:$C$5"); + chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5", 0); + chart_add_series(chart1, NULL, "=Sheet1!$B$1:$B$5", 0); + chart_add_series(chart1, NULL, "=Sheet1!$C$1:$C$5", 0); - chart_add_series(chart2, NULL, "=Sheet1!$A$1:$A$5"); - chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart2, NULL, "=Sheet1!$C$1:$C$5"); + chart_add_series(chart2, NULL, "=Sheet1!$A$1:$A$5", 0); + chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5", 0); + chart_add_series(chart2, NULL, "=Sheet1!$C$1:$C$5", 0); chartsheet_set_chart(chartsheet1, chart1); chartsheet_set_chart(chartsheet2, chart2); diff --git a/test/functional/src/test_chart_bar14.c b/test/functional/src/test_chart_bar14.c index baa3df72..fc4c7428 100644 --- a/test/functional/src/test_chart_bar14.c +++ b/test/functional/src/test_chart_bar14.c @@ -49,15 +49,15 @@ int main() { worksheet_write_url(worksheet2, CELL("A6"), "http://www.perl.com/" , NULL); - chart_add_series(chart3, NULL, "=Sheet2!$A$1:$A$5"); - chart_add_series(chart3, NULL, "=Sheet2!$B$1:$B$5"); - chart_add_series(chart3, NULL, "=Sheet2!$C$1:$C$5"); + chart_add_series(chart3, NULL, "=Sheet2!$A$1:$A$5", 0); + chart_add_series(chart3, NULL, "=Sheet2!$B$1:$B$5", 0); + chart_add_series(chart3, NULL, "=Sheet2!$C$1:$C$5", 0); - chart_add_series(chart1, NULL, "=Sheet2!$A$1:$A$5"); - chart_add_series(chart1, NULL, "=Sheet2!$B$1:$B$5"); - chart_add_series(chart1, NULL, "=Sheet2!$C$1:$C$5"); + chart_add_series(chart1, NULL, "=Sheet2!$A$1:$A$5", 0); + chart_add_series(chart1, NULL, "=Sheet2!$B$1:$B$5", 0); + chart_add_series(chart1, NULL, "=Sheet2!$C$1:$C$5", 0); - chart_add_series(chart2, NULL, "=Sheet2!$A$1:$A$5"); + chart_add_series(chart2, NULL, "=Sheet2!$A$1:$A$5", 0); worksheet_insert_chart(worksheet2, CELL("E9"), chart1); worksheet_insert_chart(worksheet2, CELL("F25"), chart2); diff --git a/test/functional/src/test_chart_bar15.c b/test/functional/src/test_chart_bar15.c index c03f2f4e..fe569a07 100644 --- a/test/functional/src/test_chart_bar15.c +++ b/test/functional/src/test_chart_bar15.c @@ -42,11 +42,11 @@ int main() { } } - chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5"); - chart_add_series(chart1, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart1, NULL, "=Sheet1!$C$1:$C$5"); + chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5", 0); + chart_add_series(chart1, NULL, "=Sheet1!$B$1:$B$5", 0); + chart_add_series(chart1, NULL, "=Sheet1!$C$1:$C$5", 0); - chart_add_series(chart2, NULL, "=Sheet2!$A$1:$A$5"); + chart_add_series(chart2, NULL, "=Sheet2!$A$1:$A$5", 0); chartsheet_set_chart(chartsheet1, chart1); chartsheet_set_chart(chartsheet2, chart2); diff --git a/test/functional/src/test_chart_bar16.c b/test/functional/src/test_chart_bar16.c index 90f73fe5..82ead347 100644 --- a/test/functional/src/test_chart_bar16.c +++ b/test/functional/src/test_chart_bar16.c @@ -34,9 +34,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_title_set_name(chart, "Title"); chart_axis_set_name(chart->x_axis, "Apple"); diff --git a/test/functional/src/test_chart_bar17.c b/test/functional/src/test_chart_bar17.c index 52e4ace7..93acf28d 100644 --- a/test/functional/src/test_chart_bar17.c +++ b/test/functional/src/test_chart_bar17.c @@ -34,9 +34,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); chartsheet_activate(chartsheet); diff --git a/test/functional/src/test_chart_bar18.c b/test/functional/src/test_chart_bar18.c index 1a8324c7..886b2821 100644 --- a/test/functional/src/test_chart_bar18.c +++ b/test/functional/src/test_chart_bar18.c @@ -34,9 +34,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); diff --git a/test/functional/src/test_chart_bar19.c b/test/functional/src/test_chart_bar19.c index 07193160..b8e846ca 100644 --- a/test/functional/src/test_chart_bar19.c +++ b/test/functional/src/test_chart_bar19.c @@ -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 *series1 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series1 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL, 0); chart_series_set_values(series1, "Sheet1", 0, 0, 4, 0); chart_series_set_values(series2, "Sheet1", 0, 1, 4, 1); diff --git a/test/functional/src/test_chart_bar20.c b/test/functional/src/test_chart_bar20.c index 3066555f..d0eccd75 100644 --- a/test/functional/src/test_chart_bar20.c +++ b/test/functional/src/test_chart_bar20.c @@ -35,9 +35,9 @@ int main() { worksheet_write_string(worksheet, CELL("A7"), "Pear" , NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); chart_series_set_name(series2, "Apple"); chart_series_set_name(series3, "=Sheet1!$A$7"); diff --git a/test/functional/src/test_chart_bar21.c b/test/functional/src/test_chart_bar21.c index 581f52b4..6f2241e3 100644 --- a/test/functional/src/test_chart_bar21.c +++ b/test/functional/src/test_chart_bar21.c @@ -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); diff --git a/test/functional/src/test_chart_bar22.c b/test/functional/src/test_chart_bar22.c index dcca338d..0fbd5176 100644 --- a/test/functional/src/test_chart_bar22.c +++ b/test/functional/src/test_chart_bar22.c @@ -50,17 +50,17 @@ int main() { chart_add_series(chart, "=Sheet1!$A$2:$A$5", "=Sheet1!$B$2:$B$5" - ); + , 0); chart_add_series(chart, "=Sheet1!$A$2:$A$5", "=Sheet1!$C$2:$C$5" - ); + , 0); chart_add_series(chart, "=Sheet1!$A$2:$A$5", "=Sheet1!$D$2:$D$5" - ); + , 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_bar24.c b/test/functional/src/test_chart_bar24.c new file mode 100644 index 00000000..e95e627a --- /dev/null +++ b/test/functional/src/test_chart_bar24.c @@ -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_bar24.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_BAR); + + /* 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 = 65934464; + chart->axis_id_4 = 72628864; + + uint8_t data1[5] = {27, 33, 44, 12, 1}; + 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); +} diff --git a/test/functional/src/test_chart_bar51.c b/test/functional/src/test_chart_bar51.c index 036146ad..68a77816 100644 --- a/test/functional/src/test_chart_bar51.c +++ b/test/functional/src/test_chart_bar51.c @@ -31,8 +31,8 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col] , NULL); - series1 = chart_add_series(chart, NULL, "Sheet1!$A$1:$A$5"); - series2 = chart_add_series(chart, NULL, "Sheet1!$B$1:$B$5"); + series1 = chart_add_series(chart, NULL, "Sheet1!$A$1:$A$5", 0); + series2 = chart_add_series(chart, NULL, "Sheet1!$B$1:$B$5", 0); /* Add the cached data for testing. */ diff --git a/test/functional/src/test_chart_bar52.c b/test/functional/src/test_chart_bar52.c index 0b9ffd62..2246aec8 100644 --- a/test/functional/src/test_chart_bar52.c +++ b/test/functional/src/test_chart_bar52.c @@ -36,8 +36,8 @@ int main() { worksheet_write_string(worksheet1, CELL("A1"), "Foo" , NULL); - lxw_chart_series *series1 = chart_add_series(chart, "Sheet2!$A$1:$A$5", "Sheet2!$B$1:$B$5"); - lxw_chart_series *series2 = chart_add_series(chart, "Sheet2!$A$1:$A$5", "Sheet2!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, "Sheet2!$A$1:$A$5", "Sheet2!$B$1:$B$5", 0); + lxw_chart_series *series2 = chart_add_series(chart, "Sheet2!$A$1:$A$5", "Sheet2!$C$1:$C$5", 0); /* Add cache data for testing. */ lxw_chart_add_data_cache(series1->categories, data[0], 5, 3, 0); diff --git a/test/functional/src/test_chart_bar53.c b/test/functional/src/test_chart_bar53.c index c2dd2d9a..ebe86a6e 100644 --- a/test/functional/src/test_chart_bar53.c +++ b/test/functional/src/test_chart_bar53.c @@ -40,24 +40,24 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart1, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart1, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); worksheet_insert_chart(worksheet, CELL("E9"), chart1); lxw_chart_series *series3 = chart_add_series(chart2, "=Sheet1!$A$1:$A$4", "=Sheet1!$B$1:$B$4" - ); + , 0); lxw_chart_series *series4 = chart_add_series(chart2, "=Sheet1!$A$1:$A$4", "=Sheet1!$C$1:$C$4" - ); + , 0); worksheet_insert_chart(worksheet, CELL("F25"), chart2); diff --git a/test/functional/src/test_chart_bar54.c b/test/functional/src/test_chart_bar54.c index 516fe2f9..ca51a38e 100644 --- a/test/functional/src/test_chart_bar54.c +++ b/test/functional/src/test_chart_bar54.c @@ -44,12 +44,12 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart1, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart1, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); worksheet_insert_chart(worksheet1, CELL("E9"), chart1); @@ -57,12 +57,12 @@ int main() { lxw_chart_series *series3 = chart_add_series(chart2, "=Sheet2!$A$1:$A$5", "=Sheet2!$B$1:$B$5" - ); + , 0); lxw_chart_series *series4 = chart_add_series(chart2, "=Sheet2!$A$1:$A$5", "=Sheet2!$C$1:$C$5" - ); + , 0); worksheet_insert_chart(worksheet2, CELL("E9"), chart2); diff --git a/test/functional/src/test_chart_bar55.c b/test/functional/src/test_chart_bar55.c index 432e77db..1ad4932e 100644 --- a/test/functional/src/test_chart_bar55.c +++ b/test/functional/src/test_chart_bar55.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); /* Add cache data for testing. */ lxw_chart_add_data_cache(series1->values, data[0], 5, 3, 0); diff --git a/test/functional/src/test_chart_bar61.c b/test/functional/src/test_chart_bar61.c index 8c8cbc3e..68d2610c 100644 --- a/test/functional/src/test_chart_bar61.c +++ b/test/functional/src/test_chart_bar61.c @@ -33,8 +33,8 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col] , NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series1 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL, 0); chart_series_set_categories(series1, "Sheet1", 0, 0, 4, 0); diff --git a/test/functional/src/test_chart_bar65.c b/test/functional/src/test_chart_bar65.c index f567512b..82350dbc 100644 --- a/test/functional/src/test_chart_bar65.c +++ b/test/functional/src/test_chart_bar65.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL, 0); chart_series_set_values(series1, "Sheet1", 0, 0, 4, 0); chart_series_set_values(series2, "Sheet1", 0, 1, 4, 1); diff --git a/test/functional/src/test_chart_bar69.c b/test/functional/src/test_chart_bar69.c index 5075c5de..6a6cfd8f 100644 --- a/test/functional/src/test_chart_bar69.c +++ b/test/functional/src/test_chart_bar69.c @@ -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 *series1 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series1 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL, 0); chart_series_set_values(series1, "Sheet1", 0, 0, 4, 0); chart_series_set_values(series2, "Sheet1", 0, 1, 4, 1); diff --git a/test/functional/src/test_chart_bar70.c b/test/functional/src/test_chart_bar70.c index bd81591c..00d53066 100644 --- a/test/functional/src/test_chart_bar70.c +++ b/test/functional/src/test_chart_bar70.c @@ -35,9 +35,9 @@ int main() { worksheet_write_string(worksheet, CELL("A7"), "Pear" , NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); chart_series_set_name(series2, "Apple"); chart_series_set_name(series3, "=Sheet1!$A$7"); diff --git a/test/functional/src/test_chart_blank01.c b/test/functional/src/test_chart_blank01.c index f2a37ef4..aabdbca5 100644 --- a/test/functional/src/test_chart_blank01.c +++ b/test/functional/src/test_chart_blank01.c @@ -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_show_blanks_as(chart, LXW_CHART_BLANKS_AS_GAP); diff --git a/test/functional/src/test_chart_blank02.c b/test/functional/src/test_chart_blank02.c index b3569586..ef10b5e9 100644 --- a/test/functional/src/test_chart_blank02.c +++ b/test/functional/src/test_chart_blank02.c @@ -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_show_blanks_as(chart, LXW_CHART_BLANKS_AS_ZERO); diff --git a/test/functional/src/test_chart_blank03.c b/test/functional/src/test_chart_blank03.c index bba7cf2d..192ffcc1 100644 --- a/test/functional/src/test_chart_blank03.c +++ b/test/functional/src/test_chart_blank03.c @@ -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_show_blanks_as(chart, LXW_CHART_BLANKS_AS_CONNECTED); diff --git a/test/functional/src/test_chart_blank04.c b/test/functional/src/test_chart_blank04.c index 32b31593..5d4bae9e 100644 --- a/test/functional/src/test_chart_blank04.c +++ b/test/functional/src/test_chart_blank04.c @@ -42,9 +42,9 @@ int main() { - 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_show_blanks_as(chart, LXW_CHART_BLANKS_AS_CONNECTED); diff --git a/test/functional/src/test_chart_blank05.c b/test/functional/src/test_chart_blank05.c index 5473783a..b9a3409a 100644 --- a/test/functional/src/test_chart_blank05.c +++ b/test/functional/src/test_chart_blank05.c @@ -34,9 +34,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_show_blanks_as(chart, LXW_CHART_BLANKS_AS_CONNECTED); diff --git a/test/functional/src/test_chart_blank06.c b/test/functional/src/test_chart_blank06.c index 471be039..8bab58ca 100644 --- a/test/functional/src/test_chart_blank06.c +++ b/test/functional/src/test_chart_blank06.c @@ -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_show_hidden_data(chart); diff --git a/test/functional/src/test_chart_chartarea01.c b/test/functional/src/test_chart_chartarea01.c index 5d637ee6..542c9190 100644 --- a/test/functional/src/test_chart_chartarea01.c +++ b/test/functional/src/test_chart_chartarea01.c @@ -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_line line1 = {.none = LXW_TRUE}; diff --git a/test/functional/src/test_chart_chartarea03.c b/test/functional/src/test_chart_chartarea03.c index afaa8c7a..a2a532d4 100644 --- a/test/functional/src/test_chart_chartarea03.c +++ b/test/functional/src/test_chart_chartarea03.c @@ -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_line line1 = {.dash_type = LXW_CHART_LINE_DASH_ROUND_DOT}; diff --git a/test/functional/src/test_chart_chartarea05.c b/test/functional/src/test_chart_chartarea05.c index 7a693f88..457bfdca 100644 --- a/test/functional/src/test_chart_chartarea05.c +++ b/test/functional/src/test_chart_chartarea05.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); lxw_chart_line line1 = {.dash_type = LXW_CHART_LINE_DASH_LONG_DASH, .color = 0xFFFF00}; diff --git a/test/functional/src/test_chart_chartarea06.c b/test/functional/src/test_chart_chartarea06.c index 4857f81c..7409a305 100644 --- a/test/functional/src/test_chart_chartarea06.c +++ b/test/functional/src/test_chart_chartarea06.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); lxw_chart_line line1 = {.dash_type = LXW_CHART_LINE_DASH_LONG_DASH, .color = 0xFFFF00}; diff --git a/test/functional/src/test_chart_clustered01.c b/test/functional/src/test_chart_clustered01.c new file mode 100644 index 00000000..ae1691d6 --- /dev/null +++ b/test/functional/src/test_chart_clustered01.c @@ -0,0 +1,78 @@ +/***************************************************************************** + * 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_clustered01.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 45886080; + chart->axis_id_2 = 45928832; + + /* Write the worksheet data. */ + worksheet_write_string(worksheet, 0, 0, "Types", NULL); + worksheet_write_string(worksheet, 0, 1, "Sub Type", NULL); + worksheet_write_string(worksheet, 0, 2, "Value 1", NULL); + worksheet_write_string(worksheet, 0, 3, "Value 2", NULL); + worksheet_write_string(worksheet, 0, 4, "Value 3", NULL); + + worksheet_write_string(worksheet, 1, 0, "Type 1", NULL); + worksheet_write_string(worksheet, 1, 1, "Sub Type A", NULL); + worksheet_write_number(worksheet, 1, 2, 5000, NULL); + worksheet_write_number(worksheet, 1, 3, 8000, NULL); + worksheet_write_number(worksheet, 1, 4, 6000, NULL); + + worksheet_write_string(worksheet, 2, 0, "", NULL); + worksheet_write_string(worksheet, 2, 1, "Sub Type B", NULL); + worksheet_write_number(worksheet, 2, 2, 2000, NULL); + worksheet_write_number(worksheet, 2, 3, 3000, NULL); + worksheet_write_number(worksheet, 2, 4, 4000, NULL); + + worksheet_write_string(worksheet, 3, 0, "", NULL); + worksheet_write_string(worksheet, 3, 1, "Sub Type C", NULL); + worksheet_write_number(worksheet, 3, 2, 250, NULL); + worksheet_write_number(worksheet, 3, 3, 1000, NULL); + worksheet_write_number(worksheet, 3, 4, 2000, NULL); + + worksheet_write_string(worksheet, 4, 0, "Type 2", NULL); + worksheet_write_string(worksheet, 4, 1, "Sub Type D", NULL); + worksheet_write_number(worksheet, 4, 2, 6000, NULL); + worksheet_write_number(worksheet, 4, 3, 6000, NULL); + worksheet_write_number(worksheet, 4, 4, 6500, NULL); + + worksheet_write_string(worksheet, 5, 0, "", NULL); + worksheet_write_string(worksheet, 5, 1, "Sub Type E", NULL); + worksheet_write_number(worksheet, 5, 2, 500, NULL); + worksheet_write_number(worksheet, 5, 3, 300, NULL); + worksheet_write_number(worksheet, 5, 4, 200, NULL); + + lxw_chart_series *series1 = chart_add_series(chart, + "=Sheet1!$A$2:$B$6", + "=Sheet1!$C$2:$C$6"); + chart_series_set_name(series1, "=Sheet1!$C$1"); + + lxw_chart_series *series2 = chart_add_series(chart, + "=Sheet1!$A$2:$B$6", + "=Sheet1!$D$2:$D$6"); + chart_series_set_name(series2, "=Sheet1!$D$1"); + + lxw_chart_series *series3 = chart_add_series(chart, + "=Sheet1!$A$2:$B$6", + "=Sheet1!$E$2:$E$6"); + chart_series_set_name(series3, "=Sheet1!$E$1"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_column01.c b/test/functional/src/test_chart_column01.c index 6b2e46a6..29f2fdc9 100644 --- a/test/functional/src/test_chart_column01.c +++ b/test/functional/src/test_chart_column01.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_column02.c b/test/functional/src/test_chart_column02.c index 2ea1b557..90ed7a1b 100644 --- a/test/functional/src/test_chart_column02.c +++ b/test/functional/src/test_chart_column02.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_column03.c b/test/functional/src/test_chart_column03.c index 0fd467df..284a8120 100644 --- a/test/functional/src/test_chart_column03.c +++ b/test/functional/src/test_chart_column03.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_column04.c b/test/functional/src/test_chart_column04.c new file mode 100644 index 00000000..cc4c50fb --- /dev/null +++ b/test/functional/src/test_chart_column04.c @@ -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_column04.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 63591936; + chart->axis_id_2 = 63593856; + chart->axis_id_3 = 63613568; + chart->axis_id_4 = 63612032; + + 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); +} diff --git a/test/functional/src/test_chart_column05.c b/test/functional/src/test_chart_column05.c index 1fcedd7a..8049e203 100644 --- a/test/functional/src/test_chart_column05.c +++ b/test/functional/src/test_chart_column05.c @@ -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, "=Foo!$A$1:$A$5"); - chart_add_series(chart, NULL, "=Foo!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Foo!$C$1:$C$5"); + chart_add_series(chart, NULL, "=Foo!$A$1:$A$5", 0); + chart_add_series(chart, NULL, "=Foo!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Foo!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_column06.c b/test/functional/src/test_chart_column06.c index 8e26e6f9..ee259731 100644 --- a/test/functional/src/test_chart_column06.c +++ b/test/functional/src/test_chart_column06.c @@ -34,9 +34,9 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet1, 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); worksheet_insert_chart(worksheet2, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_column07.c b/test/functional/src/test_chart_column07.c index 3431d807..99de5c21 100644 --- a/test/functional/src/test_chart_column07.c +++ b/test/functional/src/test_chart_column07.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=(Sheet1!$A$1:$A$2,Sheet1!$A$4:$A$5)"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=(Sheet1!$A$1:$A$2,Sheet1!$A$4:$A$5)", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_column08.c b/test/functional/src/test_chart_column08.c index 660251f0..d9fa81dd 100644 --- a/test/functional/src/test_chart_column08.c +++ b/test/functional/src/test_chart_column08.c @@ -35,7 +35,7 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart, "=(Sheet1!$A$1:$A$2,Sheet1!$A$4:$A$5)", - "=(Sheet1!$B$1:$B$2,Sheet1!$B$4:$B$5)"); + "=(Sheet1!$B$1:$B$2,Sheet1!$B$4:$B$5)", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_column09.c b/test/functional/src/test_chart_column09.c index aecece0d..80101f2c 100644 --- a/test/functional/src/test_chart_column09.c +++ b/test/functional/src/test_chart_column09.c @@ -35,7 +35,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$5", - "=Sheet1!$B$1:$B$5"); + "=Sheet1!$B$1:$B$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_column10.c b/test/functional/src/test_chart_column10.c index a46b3a8d..b5c2865d 100644 --- a/test/functional/src/test_chart_column10.c +++ b/test/functional/src/test_chart_column10.c @@ -32,7 +32,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_column11.c b/test/functional/src/test_chart_column11.c index 9d90c55f..ddb7c110 100644 --- a/test/functional/src/test_chart_column11.c +++ b/test/functional/src/test_chart_column11.c @@ -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_set_style(chart, 1); diff --git a/test/functional/src/test_chart_column12.c b/test/functional/src/test_chart_column12.c index d8ed3956..38dc0903 100644 --- a/test/functional/src/test_chart_column12.c +++ b/test/functional/src/test_chart_column12.c @@ -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_set_style(chart, 48); diff --git a/test/functional/src/test_chart_column13.c b/test/functional/src/test_chart_column13.c index 1374e3c0..7fa2075e 100644 --- a/test/functional/src/test_chart_column13.c +++ b/test/functional/src/test_chart_column13.c @@ -25,7 +25,7 @@ int main() { worksheet_write_number(worksheet, CELL("A2"), 1, NULL); worksheet_write_number(worksheet, CELL("B2"), 2, NULL); - chart_add_series(chart, "=Sheet1!$A$1:$B$1", "=Sheet1!$A$2:$B$2"); + chart_add_series(chart, "=Sheet1!$A$1:$B$1", "=Sheet1!$A$2:$B$2", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_combined01.c b/test/functional/src/test_chart_combined01.c new file mode 100644 index 00000000..b6259986 --- /dev/null +++ b/test/functional/src/test_chart_combined01.c @@ -0,0 +1,38 @@ +/***************************************************************************** + * 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_combined01.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart1 = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart1->axis_id_1 = 84882560; + chart1->axis_id_2 = 84884096; + + uint8_t data1[5] = {2, 7, 3, 6, 2}; + uint8_t data2[5] = {20, 25, 10, 10, 20}; + + 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(chart1, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart1, NULL, "=Sheet1!$B$1:$B$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart1); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_combined02.c b/test/functional/src/test_chart_combined02.c new file mode 100644 index 00000000..2e85dd17 --- /dev/null +++ b/test/functional/src/test_chart_combined02.c @@ -0,0 +1,41 @@ +/***************************************************************************** + * 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_combined02.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart1 = workbook_add_chart(workbook, LXW_CHART_COLUMN); + lxw_chart *chart2 = workbook_add_chart(workbook, LXW_CHART_LINE); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart1->axis_id_1 = 50010001; + chart1->axis_id_2 = 50010002; + + uint8_t data1[5] = {2, 7, 3, 6, 2}; + uint8_t data2[5] = {20, 25, 10, 10, 20}; + + 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(chart1, NULL, "=Sheet1!$A$1:$A$5", 0); + chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5", 0); + + chart_combine(chart1, chart2); + + worksheet_insert_chart(worksheet, CELL("E9"), chart1); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_combined03.c b/test/functional/src/test_chart_combined03.c new file mode 100644 index 00000000..b0b9eb31 --- /dev/null +++ b/test/functional/src/test_chart_combined03.c @@ -0,0 +1,41 @@ +/***************************************************************************** + * 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_combined03.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart1 = workbook_add_chart(workbook, LXW_CHART_COLUMN); + lxw_chart *chart2 = workbook_add_chart(workbook, LXW_CHART_LINE); + + uint8_t data1[5] = {2, 7, 3, 6, 2}; + uint8_t data2[5] = {20, 25, 10, 10, 20}; + uint8_t data3[5] = {4, 2, 5, 2, 1}; + + 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); + worksheet_write_number(worksheet, row, 2, data3[row], NULL); + } + + chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart1, NULL, "=Sheet1!$B$1:$B$5"); + + chart_add_series(chart2, NULL, "=Sheet1!$C$1:$C$5"); + + chart_combine(chart1, chart2); + + worksheet_insert_chart(worksheet, CELL("E9"), chart1); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_combined04.c b/test/functional/src/test_chart_combined04.c new file mode 100644 index 00000000..59f8d466 --- /dev/null +++ b/test/functional/src/test_chart_combined04.c @@ -0,0 +1,50 @@ +/***************************************************************************** + * 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_combined04.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart1 = workbook_add_chart(workbook, LXW_CHART_COLUMN); + lxw_chart *chart2 = workbook_add_chart(workbook, LXW_CHART_LINE); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart1->axis_id_1 = 50010001; + chart1->axis_id_2 = 50010002; + chart1->axis_id_3 = 60010001; + chart1->axis_id_4 = 60010002; + + uint8_t data1[5] = {2, 7, 3, 6, 2}; + uint8_t data2[5] = {20, 25, 10, 10, 20}; + + 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); + } + + /* Primary chart series on primary axis. */ + chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5", 0); + + /* Combined chart series - use y2_axis=0 because is_secondary will + * make the chart inherit the primary chart's secondary axis IDs. */ + chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5", 0); + + /* Mark chart2 as secondary (uses chart1's secondary axis IDs). */ + chart2->is_secondary = LXW_TRUE; + + chart_combine(chart1, chart2); + + worksheet_insert_chart(worksheet, CELL("E9"), chart1); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_combined05.c b/test/functional/src/test_chart_combined05.c new file mode 100644 index 00000000..4e657eee --- /dev/null +++ b/test/functional/src/test_chart_combined05.c @@ -0,0 +1,47 @@ +/***************************************************************************** + * 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_combined05.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart1 = workbook_add_chart(workbook, LXW_CHART_BAR); + lxw_chart *chart2 = workbook_add_chart(workbook, LXW_CHART_LINE); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart1->axis_id_1 = 60914304; + chart1->axis_id_2 = 78899072; + chart1->axis_id_3 = 85542016; + chart1->axis_id_4 = 85183872; + + uint8_t data1[5] = {2, 7, 3, 6, 2}; + uint8_t data2[5] = {20, 25, 10, 10, 20}; + + 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(chart1, NULL, "=Sheet1!$A$1:$A$5"); + + chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5", 0); + + /* Mark chart2 as secondary (uses chart1's secondary axis IDs). */ + chart2->is_secondary = LXW_TRUE; + + chart_combine(chart1, chart2); + + worksheet_insert_chart(worksheet, CELL("E9"), chart1); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_combined06.c b/test/functional/src/test_chart_combined06.c new file mode 100644 index 00000000..3e672337 --- /dev/null +++ b/test/functional/src/test_chart_combined06.c @@ -0,0 +1,44 @@ +/***************************************************************************** + * 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_combined06.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart1 = workbook_add_chart(workbook, LXW_CHART_AREA); + lxw_chart *chart2 = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart1->axis_id_1 = 91755648; + chart1->axis_id_2 = 91757952; + + uint8_t data1[5] = {2, 7, 3, 6, 2}; + uint8_t data2[5] = {20, 25, 10, 10, 20}; + + 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(chart1, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5"); + + chart_combine(chart1, chart2); + + /* Set cross_between to "between" for area chart. */ + chart_axis_set_position(chart1->x_axis, LXW_CHART_AXIS_POSITION_BETWEEN); + + worksheet_insert_chart(worksheet, CELL("E9"), chart1); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_combined07.c b/test/functional/src/test_chart_combined07.c new file mode 100644 index 00000000..8817f837 --- /dev/null +++ b/test/functional/src/test_chart_combined07.c @@ -0,0 +1,44 @@ +/***************************************************************************** + * 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_combined07.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart1 = workbook_add_chart(workbook, LXW_CHART_COLUMN); + lxw_chart *chart2 = workbook_add_chart(workbook, LXW_CHART_SCATTER); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart1->axis_id_1 = 81267328; + chart1->axis_id_2 = 81297792; + + uint8_t data1[5] = {2, 3, 4, 5, 6}; + uint8_t data2[5] = {20, 25, 10, 10, 20}; + uint8_t data3[5] = {5, 10, 15, 10, 5}; + + 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); + worksheet_write_number(worksheet, row, 2, data3[row], NULL); + } + + chart_add_series(chart1, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5"); + + chart_add_series(chart2, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5"); + + chart_combine(chart1, chart2); + + worksheet_insert_chart(worksheet, CELL("E9"), chart1); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_combined08.c b/test/functional/src/test_chart_combined08.c new file mode 100644 index 00000000..b8593528 --- /dev/null +++ b/test/functional/src/test_chart_combined08.c @@ -0,0 +1,49 @@ +/***************************************************************************** + * 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_combined08.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart1 = workbook_add_chart(workbook, LXW_CHART_COLUMN); + lxw_chart *chart2 = workbook_add_chart(workbook, LXW_CHART_SCATTER); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart1->axis_id_1 = 81267328; + chart1->axis_id_2 = 81297792; + chart1->axis_id_3 = 89510656; + chart1->axis_id_4 = 84556032; + + uint8_t data1[5] = {2, 3, 4, 5, 6}; + uint8_t data2[5] = {20, 25, 10, 10, 20}; + uint8_t data3[5] = {5, 10, 15, 10, 5}; + + 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); + worksheet_write_number(worksheet, row, 2, data3[row], NULL); + } + + chart_add_series(chart1, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5"); + + chart_add_series(chart2, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5", 0); + + /* Mark chart2 as secondary (uses chart1's secondary axis IDs). */ + chart2->is_secondary = LXW_TRUE; + + chart_combine(chart1, chart2); + + worksheet_insert_chart(worksheet, CELL("E9"), chart1); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_combined09.c b/test/functional/src/test_chart_combined09.c new file mode 100644 index 00000000..4e6d421c --- /dev/null +++ b/test/functional/src/test_chart_combined09.c @@ -0,0 +1,53 @@ +/***************************************************************************** + * 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_combined09.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart1 = workbook_add_chart(workbook, LXW_CHART_COLUMN); + lxw_chart *chart2 = workbook_add_chart(workbook, LXW_CHART_LINE); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart1->axis_id_1 = 114984064; + chart1->axis_id_2 = 114985600; + chart1->axis_id_3 = 114988928; + chart1->axis_id_4 = 114987392; + + uint8_t data1[5] = {2, 7, 3, 6, 2}; + uint8_t data2[5] = {20, 25, 10, 10, 20}; + + 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(chart1, NULL, "=Sheet1!$A$1:$A$5"); + + chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5", 0); + + /* Mark chart2 as secondary (uses chart1's secondary axis IDs). */ + chart2->is_secondary = LXW_TRUE; + + /* Set font properties on primary and secondary Y axes. */ + lxw_chart_font font = {.bold = LXW_TRUE, .baseline = -1}; + + chart_axis_set_num_font(chart1->y_axis, &font); + chart_axis_set_num_font(chart1->y2_axis, &font); + + chart_combine(chart1, chart2); + + worksheet_insert_chart(worksheet, CELL("E9"), chart1); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_combined10.c b/test/functional/src/test_chart_combined10.c new file mode 100644 index 00000000..0e9d6fa9 --- /dev/null +++ b/test/functional/src/test_chart_combined10.c @@ -0,0 +1,44 @@ +/***************************************************************************** + * 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_combined10.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart_doughnut = workbook_add_chart(workbook, LXW_CHART_DOUGHNUT); + lxw_chart *chart_pie = workbook_add_chart(workbook, LXW_CHART_PIE); + + /* Write data for the doughnut chart. */ + 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); + + /* Write data for the pie chart. */ + 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_number(worksheet, 4, 8, 124, NULL); + + lxw_chart_series *series1 = chart_add_series(chart_doughnut, NULL, "=Sheet1!$H$3:$H$6"); + chart_series_set_name(series1, "=Sheet1!$H$2"); + + lxw_chart_series *series2 = chart_add_series(chart_pie, NULL, "=Sheet1!$I$3:$I$6"); + chart_series_set_name(series2, "=Sheet1!$I$2"); + + chart_combine(chart_doughnut, chart_pie); + + worksheet_insert_chart(worksheet, CELL("E9"), chart_doughnut); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_combined11.c b/test/functional/src/test_chart_combined11.c new file mode 100644 index 00000000..b160116e --- /dev/null +++ b/test/functional/src/test_chart_combined11.c @@ -0,0 +1,76 @@ +/***************************************************************************** + * 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_combined11.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart_doughnut = workbook_add_chart(workbook, LXW_CHART_DOUGHNUT); + lxw_chart *chart_pie = workbook_add_chart(workbook, LXW_CHART_PIE); + + /* Write data for the doughnut chart. */ + 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); + + /* Write data for the pie chart. */ + 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_number(worksheet, 4, 8, 124, NULL); + + /* Set up point formatting for doughnut chart. */ + lxw_chart_fill fill_red = {.color = 0xFF0000}; + lxw_chart_fill fill_yellow = {.color = 0xFFC000}; + lxw_chart_fill fill_green = {.color = 0x00B050}; + lxw_chart_fill fill_none = {.none = LXW_TRUE}; + + lxw_chart_point point1_1 = {.fill = &fill_red}; + lxw_chart_point point1_2 = {.fill = &fill_yellow}; + lxw_chart_point point1_3 = {.fill = &fill_green}; + lxw_chart_point point1_4 = {.fill = &fill_none}; + + lxw_chart_point *points1[] = {&point1_1, &point1_2, &point1_3, &point1_4, NULL}; + + lxw_chart_series *series1 = chart_add_series(chart_doughnut, NULL, "=Sheet1!$H$3:$H$6"); + chart_series_set_name(series1, "=Sheet1!$H$2"); + chart_series_set_points(series1, points1); + + chart_set_rotation(chart_doughnut, 270); + chart_legend_set_position(chart_doughnut, LXW_CHART_LEGEND_NONE); + + /* Set chart area to have no border and no fill. */ + lxw_chart_line line_none = {.none = LXW_TRUE}; + chart_chartarea_set_line(chart_doughnut, &line_none); + chart_chartarea_set_fill(chart_doughnut, &fill_none); + + /* Set up point formatting for pie chart. */ + lxw_chart_point point2_1 = {.fill = &fill_none}; + lxw_chart_point point2_2 = {.fill = &fill_red}; + lxw_chart_point point2_3 = {.fill = &fill_none}; + + lxw_chart_point *points2[] = {&point2_1, &point2_2, &point2_3, NULL}; + + lxw_chart_series *series2 = chart_add_series(chart_pie, NULL, "=Sheet1!$I$3:$I$6"); + chart_series_set_name(series2, "=Sheet1!$I$2"); + chart_series_set_points(series2, points2); + + chart_set_rotation(chart_pie, 270); + + chart_combine(chart_doughnut, chart_pie); + + worksheet_insert_chart(worksheet, CELL("A1"), chart_doughnut); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_crossing01.c b/test/functional/src/test_chart_crossing01.c index c00f5b91..c5842209 100644 --- a/test/functional/src/test_chart_crossing01.c +++ b/test/functional/src/test_chart_crossing01.c @@ -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_crossing_max(chart->y_axis); diff --git a/test/functional/src/test_chart_crossing02.c b/test/functional/src/test_chart_crossing02.c index a7d1ac6d..ef74749d 100644 --- a/test/functional/src/test_chart_crossing02.c +++ b/test/functional/src/test_chart_crossing02.c @@ -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_crossing(chart->x_axis, 3); chart_axis_set_crossing(chart->y_axis, 8); diff --git a/test/functional/src/test_chart_crossing03.c b/test/functional/src/test_chart_crossing03.c index 8b092552..613b53a3 100644 --- a/test/functional/src/test_chart_crossing03.c +++ b/test/functional/src/test_chart_crossing03.c @@ -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_crossing_max(chart->x_axis); chart_axis_set_crossing_max(chart->y_axis); diff --git a/test/functional/src/test_chart_crossing04.c b/test/functional/src/test_chart_crossing04.c index f3b8f323..5f34e945 100644 --- a/test/functional/src/test_chart_crossing04.c +++ b/test/functional/src/test_chart_crossing04.c @@ -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_crossing(chart->x_axis, 3); chart_axis_set_crossing(chart->y_axis, 8); diff --git a/test/functional/src/test_chart_crossing05.c b/test/functional/src/test_chart_crossing05.c index 372c6040..10d909be 100644 --- a/test/functional/src/test_chart_crossing05.c +++ b/test/functional/src/test_chart_crossing05.c @@ -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_crossing_min(chart->x_axis); diff --git a/test/functional/src/test_chart_crossing06.c b/test/functional/src/test_chart_crossing06.c index 42605988..1b9a5ed7 100644 --- a/test/functional/src/test_chart_crossing06.c +++ b/test/functional/src/test_chart_crossing06.c @@ -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_crossing_min(chart->y_axis); diff --git a/test/functional/src/test_chart_data_labels01.c b/test/functional/src/test_chart_data_labels01.c index 36fb5eb9..eb2d1c79 100644 --- a/test/functional/src/test_chart_data_labels01.c +++ b/test/functional/src/test_chart_data_labels01.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = 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_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels02.c b/test/functional/src/test_chart_data_labels02.c index eb871587..55bc02e8 100644 --- a/test/functional/src/test_chart_data_labels02.c +++ b/test/functional/src/test_chart_data_labels02.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = 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_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels03.c b/test/functional/src/test_chart_data_labels03.c index e65c1c94..6c7dd1ef 100644 --- a/test/functional/src/test_chart_data_labels03.c +++ b/test/functional/src/test_chart_data_labels03.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = 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_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels04.c b/test/functional/src/test_chart_data_labels04.c index 7a53517a..682a5796 100644 --- a/test/functional/src/test_chart_data_labels04.c +++ b/test/functional/src/test_chart_data_labels04.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = 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_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels05.c b/test/functional/src/test_chart_data_labels05.c index 3b989295..a97801c2 100644 --- a/test/functional/src/test_chart_data_labels05.c +++ b/test/functional/src/test_chart_data_labels05.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); chart_series_set_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels06.c b/test/functional/src/test_chart_data_labels06.c index f37292ae..67b1b1ea 100644 --- a/test/functional/src/test_chart_data_labels06.c +++ b/test/functional/src/test_chart_data_labels06.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); chart_series_set_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels07.c b/test/functional/src/test_chart_data_labels07.c index 83d661f9..e49825f9 100644 --- a/test/functional/src/test_chart_data_labels07.c +++ b/test/functional/src/test_chart_data_labels07.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_series_set_labels(series1); chart_series_set_labels_position(series1, LXW_CHART_LABEL_POSITION_CENTER); diff --git a/test/functional/src/test_chart_data_labels08.c b/test/functional/src/test_chart_data_labels08.c index cd32ffcb..04fbf68d 100644 --- a/test/functional/src/test_chart_data_labels08.c +++ b/test/functional/src/test_chart_data_labels08.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_series_set_labels(series1); chart_series_set_labels_position(series1, LXW_CHART_LABEL_POSITION_RIGHT); diff --git a/test/functional/src/test_chart_data_labels09.c b/test/functional/src/test_chart_data_labels09.c index 63160b4f..e1f3cc32 100644 --- a/test/functional/src/test_chart_data_labels09.c +++ b/test/functional/src/test_chart_data_labels09.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); chart_series_set_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels10.c b/test/functional/src/test_chart_data_labels10.c index 2daedf99..e473856a 100644 --- a/test/functional/src/test_chart_data_labels10.c +++ b/test/functional/src/test_chart_data_labels10.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); chart_series_set_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels11.c b/test/functional/src/test_chart_data_labels11.c index 38da5678..605b6e99 100644 --- a/test/functional/src/test_chart_data_labels11.c +++ b/test/functional/src/test_chart_data_labels11.c @@ -29,7 +29,7 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_series_set_labels(series1); chart_series_set_labels_position(series1, LXW_CHART_LABEL_POSITION_BEST_FIT); diff --git a/test/functional/src/test_chart_data_labels12.c b/test/functional/src/test_chart_data_labels12.c index 7c567de2..23123619 100644 --- a/test/functional/src/test_chart_data_labels12.c +++ b/test/functional/src/test_chart_data_labels12.c @@ -29,7 +29,7 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_series_set_labels(series1); chart_series_set_labels_position(series1, LXW_CHART_LABEL_POSITION_OUTSIDE_END); diff --git a/test/functional/src/test_chart_data_labels13.c b/test/functional/src/test_chart_data_labels13.c index 6c2c255e..21dd1857 100644 --- a/test/functional/src/test_chart_data_labels13.c +++ b/test/functional/src/test_chart_data_labels13.c @@ -29,7 +29,7 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_series_set_labels(series1); chart_series_set_labels_position(series1, LXW_CHART_LABEL_POSITION_INSIDE_END); diff --git a/test/functional/src/test_chart_data_labels14.c b/test/functional/src/test_chart_data_labels14.c index 8fa903c4..f390db91 100644 --- a/test/functional/src/test_chart_data_labels14.c +++ b/test/functional/src/test_chart_data_labels14.c @@ -29,7 +29,7 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_series_set_labels(series1); chart_series_set_labels_position(series1, LXW_CHART_LABEL_POSITION_CENTER); diff --git a/test/functional/src/test_chart_data_labels15.c b/test/functional/src/test_chart_data_labels15.c index 09ddfff5..d42bb47b 100644 --- a/test/functional/src/test_chart_data_labels15.c +++ b/test/functional/src/test_chart_data_labels15.c @@ -29,7 +29,7 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_series_set_labels(series1); chart_series_set_labels_position(series1, LXW_CHART_LABEL_POSITION_BEST_FIT); diff --git a/test/functional/src/test_chart_data_labels16.c b/test/functional/src/test_chart_data_labels16.c index 64482fcc..3274aac4 100644 --- a/test/functional/src/test_chart_data_labels16.c +++ b/test/functional/src/test_chart_data_labels16.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_series_set_labels(series1); chart_series_set_labels_position(series1, LXW_CHART_LABEL_POSITION_CENTER); diff --git a/test/functional/src/test_chart_data_labels18.c b/test/functional/src/test_chart_data_labels18.c index ec747976..a16b9284 100644 --- a/test/functional/src/test_chart_data_labels18.c +++ b/test/functional/src/test_chart_data_labels18.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); chart_series_set_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels19.c b/test/functional/src/test_chart_data_labels19.c index 10e6d673..fa540d60 100644 --- a/test/functional/src/test_chart_data_labels19.c +++ b/test/functional/src/test_chart_data_labels19.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); chart_series_set_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels20.c b/test/functional/src/test_chart_data_labels20.c index df7bbda8..d9d3cc22 100644 --- a/test/functional/src/test_chart_data_labels20.c +++ b/test/functional/src/test_chart_data_labels20.c @@ -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 *series1 = 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 *series1 = 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_labels(series1); chart_series_set_labels_legend(series1); diff --git a/test/functional/src/test_chart_data_labels21.c b/test/functional/src/test_chart_data_labels21.c index 862b8514..93cb751c 100644 --- a/test/functional/src/test_chart_data_labels21.c +++ b/test/functional/src/test_chart_data_labels21.c @@ -30,7 +30,7 @@ int main() { worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_font font = {.name = "Consolas", .pitch_family = 49, .charset = 0, .baseline = -1}; diff --git a/test/functional/src/test_chart_data_labels22.c b/test/functional/src/test_chart_data_labels22.c index 7cce9726..ed064c62 100644 --- a/test/functional/src/test_chart_data_labels22.c +++ b/test/functional/src/test_chart_data_labels22.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = 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_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels23.c b/test/functional/src/test_chart_data_labels23.c index 7b9fb5f0..7f576acf 100644 --- a/test/functional/src/test_chart_data_labels23.c +++ b/test/functional/src/test_chart_data_labels23.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = 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 = {.name = "Consolas", .pitch_family = 49, .charset = 0, .baseline = -1}; diff --git a/test/functional/src/test_chart_data_labels24.c b/test/functional/src/test_chart_data_labels24.c index 9c8ca2d4..7aadf744 100644 --- a/test/functional/src/test_chart_data_labels24.c +++ b/test/functional/src/test_chart_data_labels24.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = 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 = {.name = "Consolas", .size = 12, .pitch_family = 49, .charset = 0, .baseline = -1}; diff --git a/test/functional/src/test_chart_data_labels25.c b/test/functional/src/test_chart_data_labels25.c index f32cffd0..0dfc043f 100644 --- a/test/functional/src/test_chart_data_labels25.c +++ b/test/functional/src/test_chart_data_labels25.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = 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}; lxw_chart_font font2 = {.rotation = -45, .baseline = -1}; diff --git a/test/functional/src/test_chart_data_labels26.c b/test/functional/src/test_chart_data_labels26.c index ca3e0847..59baa594 100644 --- a/test/functional/src/test_chart_data_labels26.c +++ b/test/functional/src/test_chart_data_labels26.c @@ -33,15 +33,15 @@ int main() { for (col = 0; col < 4; 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_data_label data_label1 = {.value = "33"}; lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels27.c b/test/functional/src/test_chart_data_labels27.c index 34533605..48260de7 100644 --- a/test/functional/src/test_chart_data_labels27.c +++ b/test/functional/src/test_chart_data_labels27.c @@ -33,15 +33,15 @@ int main() { for (col = 0; col < 4; 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_data_label data_label1 = {.value = "=Sheet1!$D$1"}; lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels28.c b/test/functional/src/test_chart_data_labels28.c index 07637c55..f7e2b9ac 100644 --- a/test/functional/src/test_chart_data_labels28.c +++ b/test/functional/src/test_chart_data_labels28.c @@ -36,7 +36,7 @@ int main() { worksheet_write_string(worksheet, CELL("D1"), "foo" , NULL); worksheet_write_string(worksheet, CELL("D2"), "bar" , NULL); - lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_data_label data_label1 = {.value = "123"}; @@ -56,8 +56,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels29.c b/test/functional/src/test_chart_data_labels29.c index a71df0be..7a18a4ab 100644 --- a/test/functional/src/test_chart_data_labels29.c +++ b/test/functional/src/test_chart_data_labels29.c @@ -34,15 +34,15 @@ int main() { worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_data_label data_label1 = {.hide = LXW_TRUE}; lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels30.c b/test/functional/src/test_chart_data_labels30.c index 19f79359..e3625fee 100644 --- a/test/functional/src/test_chart_data_labels30.c +++ b/test/functional/src/test_chart_data_labels30.c @@ -33,7 +33,7 @@ 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_data_label data_label1 = {.hide = LXW_TRUE}; lxw_chart_data_label data_label2 = {0}; @@ -41,8 +41,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels31.c b/test/functional/src/test_chart_data_labels31.c index c7ad8d0f..638db817 100644 --- a/test/functional/src/test_chart_data_labels31.c +++ b/test/functional/src/test_chart_data_labels31.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 4; 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_data_label data_label1 = {.value = "33"}; lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; @@ -41,8 +41,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); chart_series_set_labels_options(series, LXW_TRUE, LXW_TRUE, LXW_TRUE); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels32.c b/test/functional/src/test_chart_data_labels32.c index cc2bf31f..2ef5e74a 100644 --- a/test/functional/src/test_chart_data_labels32.c +++ b/test/functional/src/test_chart_data_labels32.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 4; 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_font font1 = {.bold = LXW_TRUE, .italic = LXW_TRUE, .color = LXW_COLOR_RED, .baseline = -1}; lxw_chart_data_label data_label1 = {.value = "33", .font = &font1}; @@ -41,8 +41,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels33.c b/test/functional/src/test_chart_data_labels33.c index dae0c953..31fe7bdb 100644 --- a/test/functional/src/test_chart_data_labels33.c +++ b/test/functional/src/test_chart_data_labels33.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 4; 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_font font1 = {.bold = LXW_TRUE, .italic = LXW_TRUE, .baseline = -1}; lxw_chart_data_label data_label1 = {.font = &font1}; @@ -41,8 +41,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels34.c b/test/functional/src/test_chart_data_labels34.c index 132c3f06..9923ab4c 100644 --- a/test/functional/src/test_chart_data_labels34.c +++ b/test/functional/src/test_chart_data_labels34.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 4; 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_font font1 = {.bold = LXW_TRUE, .italic = LXW_TRUE, .color = LXW_COLOR_RED, .baseline = -1}; lxw_chart_data_label data_label1 = {. value = "=Sheet1!$D$1", .font = &font1}; @@ -41,8 +41,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels35.c b/test/functional/src/test_chart_data_labels35.c index 61855823..0f20546e 100644 --- a/test/functional/src/test_chart_data_labels35.c +++ b/test/functional/src/test_chart_data_labels35.c @@ -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); lxw_chart_line line = {.color = LXW_COLOR_RED}; diff --git a/test/functional/src/test_chart_data_labels36.c b/test/functional/src/test_chart_data_labels36.c index b9237706..ed41d758 100644 --- a/test/functional/src/test_chart_data_labels36.c +++ b/test/functional/src/test_chart_data_labels36.c @@ -30,7 +30,7 @@ int main() { worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_font font = {.name = "Consolas", .pitch_family = 49, .charset = 0, .baseline = -1}; lxw_chart_line line = {.color = LXW_COLOR_RED}; diff --git a/test/functional/src/test_chart_data_labels37.c b/test/functional/src/test_chart_data_labels37.c index 0a4a5d82..6c4e2ebf 100644 --- a/test/functional/src/test_chart_data_labels37.c +++ b/test/functional/src/test_chart_data_labels37.c @@ -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); lxw_chart_line line = {.color = LXW_COLOR_RED, .width = 1, diff --git a/test/functional/src/test_chart_data_labels38.c b/test/functional/src/test_chart_data_labels38.c index 24292c5f..4c9d063f 100644 --- a/test/functional/src/test_chart_data_labels38.c +++ b/test/functional/src/test_chart_data_labels38.c @@ -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); lxw_chart_line line = {.color = LXW_COLOR_RED, .width = 1, diff --git a/test/functional/src/test_chart_data_labels40.c b/test/functional/src/test_chart_data_labels40.c index 5d72b2f4..07bc7a5f 100644 --- a/test/functional/src/test_chart_data_labels40.c +++ b/test/functional/src/test_chart_data_labels40.c @@ -33,7 +33,7 @@ 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_line line = {.color = LXW_COLOR_RED}; @@ -42,8 +42,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels41.c b/test/functional/src/test_chart_data_labels41.c index 963ac8ec..4993cf05 100644 --- a/test/functional/src/test_chart_data_labels41.c +++ b/test/functional/src/test_chart_data_labels41.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 4; 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_line line = {.color = LXW_COLOR_RED}; @@ -42,8 +42,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels42.c b/test/functional/src/test_chart_data_labels42.c index 4148a64a..8d082c80 100644 --- a/test/functional/src/test_chart_data_labels42.c +++ b/test/functional/src/test_chart_data_labels42.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 4; 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_line line = {.color = LXW_COLOR_RED}; lxw_chart_font font = {.color = LXW_COLOR_RED, .baseline = -1}; @@ -43,8 +43,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels43.c b/test/functional/src/test_chart_data_labels43.c index d61e00af..50ed4869 100644 --- a/test/functional/src/test_chart_data_labels43.c +++ b/test/functional/src/test_chart_data_labels43.c @@ -33,7 +33,7 @@ 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_line line = {.color = LXW_COLOR_RED}; lxw_chart_font font = {.bold = LXW_TRUE, .italic = LXW_TRUE, .color = LXW_COLOR_RED, .baseline = -1}; @@ -43,8 +43,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels44.c b/test/functional/src/test_chart_data_labels44.c index adb3c7fe..ee9f1350 100644 --- a/test/functional/src/test_chart_data_labels44.c +++ b/test/functional/src/test_chart_data_labels44.c @@ -33,7 +33,7 @@ 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_line line = {.color = LXW_COLOR_RED}; lxw_chart_fill fill = {.color = 0x00B050}; @@ -43,8 +43,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels45.c b/test/functional/src/test_chart_data_labels45.c index 09f6af92..98984a24 100644 --- a/test/functional/src/test_chart_data_labels45.c +++ b/test/functional/src/test_chart_data_labels45.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 4; 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_line line = {.color = LXW_COLOR_RED}; lxw_chart_fill fill = {.color = 0x00B050}; @@ -42,8 +42,8 @@ int main() { lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels46.c b/test/functional/src/test_chart_data_labels46.c index aafe0bff..3401e738 100644 --- a/test/functional/src/test_chart_data_labels46.c +++ b/test/functional/src/test_chart_data_labels46.c @@ -33,7 +33,7 @@ int main() { for (col = 0; col < 4; 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_line line = {.color = LXW_COLOR_RED}; lxw_chart_font font = {.color = LXW_COLOR_RED, .baseline = -1}; @@ -44,8 +44,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels47.c b/test/functional/src/test_chart_data_labels47.c index fa3f3f80..e5997c0a 100644 --- a/test/functional/src/test_chart_data_labels47.c +++ b/test/functional/src/test_chart_data_labels47.c @@ -33,7 +33,7 @@ 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"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); lxw_chart_line line = {.color = LXW_COLOR_RED}; lxw_chart_font font = {.bold = LXW_TRUE, .italic = LXW_TRUE, .color = LXW_COLOR_RED, .baseline = -1}; @@ -44,8 +44,8 @@ int main() { chart_series_set_labels_custom(series, data_labels); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_data_labels48.c b/test/functional/src/test_chart_data_labels48.c index 02f549e5..66faf315 100644 --- a/test/functional/src/test_chart_data_labels48.c +++ b/test/functional/src/test_chart_data_labels48.c @@ -38,9 +38,9 @@ int main() { lxw_chart_data_label *data_labels1[] = {&data_label1, NULL}; lxw_chart_data_label *data_labels2[] = {&data_label2, NULL}; - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = 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_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels49.c b/test/functional/src/test_chart_data_labels49.c index 959a9a45..9573189d 100644 --- a/test/functional/src/test_chart_data_labels49.c +++ b/test/functional/src/test_chart_data_labels49.c @@ -38,9 +38,9 @@ int main() { lxw_chart_data_label *data_labels1[] = {&data_label1, NULL}; lxw_chart_data_label *data_labels2[] = {&data_label2, NULL}; - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + lxw_chart_series *series2 = 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_labels(series1); chart_series_set_labels(series2); diff --git a/test/functional/src/test_chart_data_labels50.c b/test/functional/src/test_chart_data_labels50.c index e01c175c..7f1227ac 100644 --- a/test/functional/src/test_chart_data_labels50.c +++ b/test/functional/src/test_chart_data_labels50.c @@ -41,12 +41,12 @@ int main() { lxw_chart_data_label data_label1 = {.line = &line, .font = &font}; lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; - lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_series_set_labels_custom(series, data_labels); chart_series_set_labels_position(series, LXW_CHART_LABEL_POSITION_CENTER); - 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!$B$1:$B$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_date01.c b/test/functional/src/test_chart_date01.c new file mode 100644 index 00000000..3d3990f3 --- /dev/null +++ b/test/functional/src/test_chart_date01.c @@ -0,0 +1,62 @@ +/***************************************************************************** + * 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_date01.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE); + + /* Date format. */ + lxw_format *date_format = workbook_add_format(workbook); + format_set_num_format_index(date_format, 14); + + /* Set column width. */ + worksheet_set_column(worksheet, 0, 0, 12, NULL); + + /* Write date values (2013-01-01 to 2013-01-10). */ + lxw_datetime dates[] = { + {2013, 1, 1, 0, 0, 0.0}, + {2013, 1, 2, 0, 0, 0.0}, + {2013, 1, 3, 0, 0, 0.0}, + {2013, 1, 4, 0, 0, 0.0}, + {2013, 1, 5, 0, 0, 0.0}, + {2013, 1, 6, 0, 0, 0.0}, + {2013, 1, 7, 0, 0, 0.0}, + {2013, 1, 8, 0, 0, 0.0}, + {2013, 1, 9, 0, 0, 0.0}, + {2013, 1, 10, 0, 0, 0.0} + }; + + for (int i = 0; i < 10; i++) { + worksheet_write_datetime(worksheet, i, 0, &dates[i], date_format); + } + + /* Write data values. */ + int values[] = {10, 30, 20, 40, 20, 60, 50, 40, 30, 30}; + for (int i = 0; i < 10; i++) { + worksheet_write_number(worksheet, i, 1, values[i], NULL); + } + + /* Add chart series. */ + chart_add_series(chart, "=Sheet1!$A$1:$A$10", "=Sheet1!$B$1:$B$10"); + + /* Set the X axis as a date axis with linked format. */ + chart_axis_set_date_axis(chart->x_axis); + chart_axis_set_num_format(chart->x_axis, "dd/mm/yyyy"); + chart->x_axis->source_linked = LXW_TRUE; + + /* Insert the chart. */ + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_display_units01.c b/test/functional/src/test_chart_display_units01.c index bbf0fbae..517e0b24 100644 --- a/test/functional/src/test_chart_display_units01.c +++ b/test/functional/src/test_chart_display_units01.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_display_units02.c b/test/functional/src/test_chart_display_units02.c index 8cfa14b6..005f069c 100644 --- a/test/functional/src/test_chart_display_units02.c +++ b/test/functional/src/test_chart_display_units02.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_HUNDREDS); chart_axis_set_display_units_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_display_units03.c b/test/functional/src/test_chart_display_units03.c index 64336a85..671683dc 100644 --- a/test/functional/src/test_chart_display_units03.c +++ b/test/functional/src/test_chart_display_units03.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_THOUSANDS); chart_axis_set_display_units_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_display_units04.c b/test/functional/src/test_chart_display_units04.c index feb2b2c7..3aeb118e 100644 --- a/test/functional/src/test_chart_display_units04.c +++ b/test/functional/src/test_chart_display_units04.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_TEN_THOUSANDS); chart_axis_set_display_units_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_display_units05.c b/test/functional/src/test_chart_display_units05.c index 80c677cb..d7608f82 100644 --- a/test/functional/src/test_chart_display_units05.c +++ b/test/functional/src/test_chart_display_units05.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_HUNDRED_THOUSANDS); chart_axis_set_display_units_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_display_units06.c b/test/functional/src/test_chart_display_units06.c index c8ee60c8..a0541714 100644 --- a/test/functional/src/test_chart_display_units06.c +++ b/test/functional/src/test_chart_display_units06.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_MILLIONS); chart_axis_set_display_units_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_display_units07.c b/test/functional/src/test_chart_display_units07.c index a936568b..3e6dd440 100644 --- a/test/functional/src/test_chart_display_units07.c +++ b/test/functional/src/test_chart_display_units07.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_TEN_MILLIONS); chart_axis_set_display_units_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_display_units08.c b/test/functional/src/test_chart_display_units08.c index 9643256c..a1d156b8 100644 --- a/test/functional/src/test_chart_display_units08.c +++ b/test/functional/src/test_chart_display_units08.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_HUNDRED_MILLIONS); chart_axis_set_display_units_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_display_units09.c b/test/functional/src/test_chart_display_units09.c index 7c9e6615..c09afc06 100644 --- a/test/functional/src/test_chart_display_units09.c +++ b/test/functional/src/test_chart_display_units09.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_BILLIONS); chart_axis_set_display_units_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_display_units10.c b/test/functional/src/test_chart_display_units10.c index 361d48dc..83f4ffb5 100644 --- a/test/functional/src/test_chart_display_units10.c +++ b/test/functional/src/test_chart_display_units10.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_TRILLIONS); chart_axis_set_display_units_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_display_units11.c b/test/functional/src/test_chart_display_units11.c index ab7431e2..e95d8217 100644 --- a/test/functional/src/test_chart_display_units11.c +++ b/test/functional/src/test_chart_display_units11.c @@ -26,7 +26,7 @@ int main() { worksheet_write_number(worksheet, 3, 0, 20000000, NULL); worksheet_write_number(worksheet, 4, 0, 10000000, NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_HUNDREDS); diff --git a/test/functional/src/test_chart_display_units12.c b/test/functional/src/test_chart_display_units12.c index bca0b384..eb9f9305 100644 --- a/test/functional/src/test_chart_display_units12.c +++ b/test/functional/src/test_chart_display_units12.c @@ -35,7 +35,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); chart_axis_set_display_units(chart->y_axis, LXW_CHART_AXIS_UNITS_HUNDREDS); chart_axis_set_display_units_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_doughnut01.c b/test/functional/src/test_chart_doughnut01.c index 0009bbdb..f714ed7d 100644 --- a/test/functional/src/test_chart_doughnut01.c +++ b/test/functional/src/test_chart_doughnut01.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_doughnut02.c b/test/functional/src/test_chart_doughnut02.c index 4c0da865..3d195f37 100644 --- a/test/functional/src/test_chart_doughnut02.c +++ b/test/functional/src/test_chart_doughnut02.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); chart_set_hole_size(chart, 10); diff --git a/test/functional/src/test_chart_doughnut03.c b/test/functional/src/test_chart_doughnut03.c index 465518b7..6116755f 100644 --- a/test/functional/src/test_chart_doughnut03.c +++ b/test/functional/src/test_chart_doughnut03.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); chart_set_hole_size(chart, 90); diff --git a/test/functional/src/test_chart_doughnut04.c b/test/functional/src/test_chart_doughnut04.c index cb4c4178..8b23d77d 100644 --- a/test/functional/src/test_chart_doughnut04.c +++ b/test/functional/src/test_chart_doughnut04.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); chart_set_rotation(chart, 30); diff --git a/test/functional/src/test_chart_doughnut05.c b/test/functional/src/test_chart_doughnut05.c index 3f2ab397..2fedaa28 100644 --- a/test/functional/src/test_chart_doughnut05.c +++ b/test/functional/src/test_chart_doughnut05.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); chart_set_rotation(chart, 360); diff --git a/test/functional/src/test_chart_doughnut06.c b/test/functional/src/test_chart_doughnut06.c index 9f07eed4..9c66a3d0 100644 --- a/test/functional/src/test_chart_doughnut06.c +++ b/test/functional/src/test_chart_doughnut06.c @@ -27,8 +27,8 @@ int main() { for (col = 0; col < 2; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); - chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_drop_lines01.c b/test/functional/src/test_chart_drop_lines01.c index 10169b50..fd660fbd 100644 --- a/test/functional/src/test_chart_drop_lines01.c +++ b/test/functional/src/test_chart_drop_lines01.c @@ -38,12 +38,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); diff --git a/test/functional/src/test_chart_drop_lines02.c b/test/functional/src/test_chart_drop_lines02.c index cf4918df..50759dc1 100644 --- a/test/functional/src/test_chart_drop_lines02.c +++ b/test/functional/src/test_chart_drop_lines02.c @@ -41,12 +41,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); diff --git a/test/functional/src/test_chart_drop_lines03.c b/test/functional/src/test_chart_drop_lines03.c index f41d4d21..670e34ac 100644 --- a/test/functional/src/test_chart_drop_lines03.c +++ b/test/functional/src/test_chart_drop_lines03.c @@ -38,12 +38,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); diff --git a/test/functional/src/test_chart_errorbars01.c b/test/functional/src/test_chart_errorbars01.c index 2b50ebd2..74b48345 100644 --- a/test/functional/src/test_chart_errorbars01.c +++ b/test/functional/src/test_chart_errorbars01.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_series_set_error_bars(series1->y_error_bars, diff --git a/test/functional/src/test_chart_errorbars02.c b/test/functional/src/test_chart_errorbars02.c index a18e9673..a466e5f6 100644 --- a/test/functional/src/test_chart_errorbars02.c +++ b/test/functional/src/test_chart_errorbars02.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); chart_series_set_error_bars(series1->y_error_bars, diff --git a/test/functional/src/test_chart_errorbars03.c b/test/functional/src/test_chart_errorbars03.c index 02c63bb7..1f32f31b 100644 --- a/test/functional/src/test_chart_errorbars03.c +++ b/test/functional/src/test_chart_errorbars03.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_line line = {.color = LXW_COLOR_RED, diff --git a/test/functional/src/test_chart_errorbars04.c b/test/functional/src/test_chart_errorbars04.c index c6f29fbb..e2d90dbe 100644 --- a/test/functional/src/test_chart_errorbars04.c +++ b/test/functional/src/test_chart_errorbars04.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_series_error_bars *x_error_bars; lxw_series_error_bars *y_error_bars; diff --git a/test/functional/src/test_chart_errorbars05.c b/test/functional/src/test_chart_errorbars05.c index a4575bf6..e9a4cf1d 100644 --- a/test/functional/src/test_chart_errorbars05.c +++ b/test/functional/src/test_chart_errorbars05.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_series_set_error_bars(series1->x_error_bars, LXW_CHART_ERROR_BAR_TYPE_STD_ERROR, 0); diff --git a/test/functional/src/test_chart_errorbars06.c b/test/functional/src/test_chart_errorbars06.c index 5a373b27..e5dd2c13 100644 --- a/test/functional/src/test_chart_errorbars06.c +++ b/test/functional/src/test_chart_errorbars06.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_series_set_error_bars(series1->y_error_bars, LXW_CHART_ERROR_BAR_TYPE_STD_ERROR, 0); diff --git a/test/functional/src/test_chart_font01.c b/test/functional/src/test_chart_font01.c index 459a88b4..7a220840 100644 --- a/test/functional/src/test_chart_font01.c +++ b/test/functional/src/test_chart_font01.c @@ -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_title_set_name(chart, "Title"); diff --git a/test/functional/src/test_chart_font02.c b/test/functional/src/test_chart_font02.c index ccf97780..93f79838 100644 --- a/test/functional/src/test_chart_font02.c +++ b/test/functional/src/test_chart_font02.c @@ -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_title_set_name(chart, "Title"); diff --git a/test/functional/src/test_chart_font03.c b/test/functional/src/test_chart_font03.c index 3f5394b7..d17bac46 100644 --- a/test/functional/src/test_chart_font03.c +++ b/test/functional/src/test_chart_font03.c @@ -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 = {.italic = LXW_TRUE}; lxw_chart_font font2 = {.bold = LXW_TRUE, .italic = LXW_TRUE}; diff --git a/test/functional/src/test_chart_font04.c b/test/functional/src/test_chart_font04.c index 2b6cb3da..7ea90892 100644 --- a/test/functional/src/test_chart_font04.c +++ b/test/functional/src/test_chart_font04.c @@ -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 = {.italic = LXW_TRUE}; lxw_chart_font font2 = {.bold = LXW_TRUE, .italic = LXW_TRUE}; diff --git a/test/functional/src/test_chart_font05.c b/test/functional/src/test_chart_font05.c index 3aa7fb26..a3414faa 100644 --- a/test/functional/src/test_chart_font05.c +++ b/test/functional/src/test_chart_font05.c @@ -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_title_set_name(chart, "Title"); diff --git a/test/functional/src/test_chart_font06.c b/test/functional/src/test_chart_font06.c index 38c96f3a..f01d0dd1 100644 --- a/test/functional/src/test_chart_font06.c +++ b/test/functional/src/test_chart_font06.c @@ -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 = {.name = "Calibri", .pitch_family = 34, .charset = 0, .color = LXW_COLOR_YELLOW}; diff --git a/test/functional/src/test_chart_font07.c b/test/functional/src/test_chart_font07.c index 763457a0..1416559f 100644 --- a/test/functional/src/test_chart_font07.c +++ b/test/functional/src/test_chart_font07.c @@ -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 = {.size = 9, .baseline = -1}; chart_legend_set_font(chart, &font1); diff --git a/test/functional/src/test_chart_font08.c b/test/functional/src/test_chart_font08.c index 89cbf040..6c2909c0 100644 --- a/test/functional/src/test_chart_font08.c +++ b/test/functional/src/test_chart_font08.c @@ -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 = {.bold = LXW_TRUE, .italic = LXW_TRUE, .baseline = -1}; chart_legend_set_font(chart, &font1); diff --git a/test/functional/src/test_chart_font09.c b/test/functional/src/test_chart_font09.c index 493538da..410f15af 100644 --- a/test/functional/src/test_chart_font09.c +++ b/test/functional/src/test_chart_font09.c @@ -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}; diff --git a/test/functional/src/test_chart_format01.c b/test/functional/src/test_chart_format01.c index 89ab1630..7de76470 100644 --- a/test/functional/src/test_chart_format01.c +++ b/test/functional/src/test_chart_format01.c @@ -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); diff --git a/test/functional/src/test_chart_format02.c b/test/functional/src/test_chart_format02.c index e7aba466..5a38687b 100644 --- a/test/functional/src/test_chart_format02.c +++ b/test/functional/src/test_chart_format02.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_line line = {.color = LXW_COLOR_RED}; diff --git a/test/functional/src/test_chart_format03.c b/test/functional/src/test_chart_format03.c index 5ce9fefc..9a918f84 100644 --- a/test/functional/src/test_chart_format03.c +++ b/test/functional/src/test_chart_format03.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_line line = {.color = LXW_COLOR_YELLOW}; lxw_chart_fill fill = {.color = LXW_COLOR_RED}; diff --git a/test/functional/src/test_chart_format04.c b/test/functional/src/test_chart_format04.c index 1ca07502..05f4d023 100644 --- a/test/functional/src/test_chart_format04.c +++ b/test/functional/src/test_chart_format04.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_fill fill = {.color = 0xFF0000}; diff --git a/test/functional/src/test_chart_format05.c b/test/functional/src/test_chart_format05.c index 0176ee68..43ade30f 100644 --- a/test/functional/src/test_chart_format05.c +++ b/test/functional/src/test_chart_format05.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_marker_type(series, LXW_CHART_MARKER_AUTOMATIC); diff --git a/test/functional/src/test_chart_format06.c b/test/functional/src/test_chart_format06.c index eb704993..47a0f06d 100644 --- a/test/functional/src/test_chart_format06.c +++ b/test/functional/src/test_chart_format06.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_marker_type(series, LXW_CHART_MARKER_DIAMOND); diff --git a/test/functional/src/test_chart_format07.c b/test/functional/src/test_chart_format07.c index 05bee6c8..8b3361e5 100644 --- a/test/functional/src/test_chart_format07.c +++ b/test/functional/src/test_chart_format07.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_line line = {.color = LXW_COLOR_YELLOW}; lxw_chart_fill fill = {.color = LXW_COLOR_RED}; diff --git a/test/functional/src/test_chart_format08.c b/test/functional/src/test_chart_format08.c index 3d810e84..3812b495 100644 --- a/test/functional/src/test_chart_format08.c +++ b/test/functional/src/test_chart_format08.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_trendline(series, LXW_CHART_TRENDLINE_TYPE_LINEAR, 0); diff --git a/test/functional/src/test_chart_format09.c b/test/functional/src/test_chart_format09.c index 424b1262..94043e06 100644 --- a/test/functional/src/test_chart_format09.c +++ b/test/functional/src/test_chart_format09.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_line line = {.color = LXW_COLOR_RED, .width = 1.25, diff --git a/test/functional/src/test_chart_format10.c b/test/functional/src/test_chart_format10.c index d1e1db24..f3fc7f95 100644 --- a/test/functional/src/test_chart_format10.c +++ b/test/functional/src/test_chart_format10.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_line line = {.color = LXW_COLOR_RED, .width = 1, diff --git a/test/functional/src/test_chart_format11.c b/test/functional/src/test_chart_format11.c index 9e3b6639..c14f411f 100644 --- a/test/functional/src/test_chart_format11.c +++ b/test/functional/src/test_chart_format11.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_line line = {.color = LXW_COLOR_RED, .width = 1, diff --git a/test/functional/src/test_chart_format12.c b/test/functional/src/test_chart_format12.c index af32e4c4..31d984c9 100644 --- a/test/functional/src/test_chart_format12.c +++ b/test/functional/src/test_chart_format12.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_line line = {.color = LXW_COLOR_RED, .width = 1, diff --git a/test/functional/src/test_chart_format13.c b/test/functional/src/test_chart_format13.c index 7c61be14..56a34fe7 100644 --- a/test/functional/src/test_chart_format13.c +++ b/test/functional/src/test_chart_format13.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_labels(series); diff --git a/test/functional/src/test_chart_format14.c b/test/functional/src/test_chart_format14.c index a64fe77e..91307a0d 100644 --- a/test/functional/src/test_chart_format14.c +++ b/test/functional/src/test_chart_format14.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_labels(series); chart_series_set_labels_options(series, LXW_TRUE, LXW_TRUE, LXW_TRUE); diff --git a/test/functional/src/test_chart_format15.c b/test/functional/src/test_chart_format15.c index f53a37c8..65260e69 100644 --- a/test/functional/src/test_chart_format15.c +++ b/test/functional/src/test_chart_format15.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_trendline(series, LXW_CHART_TRENDLINE_TYPE_LINEAR, 0); diff --git a/test/functional/src/test_chart_format16.c b/test/functional/src/test_chart_format16.c index d4e84571..0bcfb17e 100644 --- a/test/functional/src/test_chart_format16.c +++ b/test/functional/src/test_chart_format16.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_labels(series); chart_series_set_labels_options(series, LXW_TRUE, LXW_TRUE, LXW_TRUE); diff --git a/test/functional/src/test_chart_format17.c b/test/functional/src/test_chart_format17.c index a4a2f295..d1eb6f2d 100644 --- a/test/functional/src/test_chart_format17.c +++ b/test/functional/src/test_chart_format17.c @@ -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 *series1 = 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 *series1 = 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_fill fill = {.none = LXW_TRUE}; chart_series_set_fill(series1, &fill); diff --git a/test/functional/src/test_chart_format18.c b/test/functional/src/test_chart_format18.c index 035e1ede..b7cd30af 100644 --- a/test/functional/src/test_chart_format18.c +++ b/test/functional/src/test_chart_format18.c @@ -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 *series1 = 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 *series1 = 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_line line = {.none = LXW_TRUE}; lxw_chart_fill fill = {.none = LXW_TRUE}; diff --git a/test/functional/src/test_chart_format19.c b/test/functional/src/test_chart_format19.c index 8a7e43b4..c129cafa 100644 --- a/test/functional/src/test_chart_format19.c +++ b/test/functional/src/test_chart_format19.c @@ -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"); - lxw_chart_series *series = 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); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); chart_series_set_labels(series); chart_series_set_labels_position(series, LXW_CHART_LABEL_POSITION_INSIDE_BASE); diff --git a/test/functional/src/test_chart_format20.c b/test/functional/src/test_chart_format20.c index 7a694f31..9f586d8f 100644 --- a/test/functional/src/test_chart_format20.c +++ b/test/functional/src/test_chart_format20.c @@ -37,11 +37,11 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart1, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart1, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart1, NULL, "=Sheet1!$B$1:$B$5", 0); + chart_add_series(chart1, NULL, "=Sheet1!$C$1:$C$5", 0); - lxw_chart_series *series2 = chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5"); - chart_add_series(chart2, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series2 = chart_add_series(chart2, NULL, "=Sheet1!$B$1:$B$5", 0); + chart_add_series(chart2, NULL, "=Sheet1!$C$1:$C$5", 0); lxw_chart_line line = {.color = LXW_COLOR_RED, diff --git a/test/functional/src/test_chart_format21.c b/test/functional/src/test_chart_format21.c index 0b4849ae..2c75334c 100644 --- a/test/functional/src/test_chart_format21.c +++ b/test/functional/src/test_chart_format21.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_line line = {.color = LXW_COLOR_YELLOW}; lxw_chart_fill fill = {.color = LXW_COLOR_RED, .transparency = 24}; diff --git a/test/functional/src/test_chart_format22.c b/test/functional/src/test_chart_format22.c index 478d04cd..da2f9b38 100644 --- a/test/functional/src/test_chart_format22.c +++ b/test/functional/src/test_chart_format22.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_line line = {.color = LXW_COLOR_YELLOW}; lxw_chart_fill fill = {.color = LXW_COLOR_RED, .transparency = 1}; diff --git a/test/functional/src/test_chart_format23.c b/test/functional/src/test_chart_format23.c index 865fe145..c528cdee 100644 --- a/test/functional/src/test_chart_format23.c +++ b/test/functional/src/test_chart_format23.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_line line = {.color = LXW_COLOR_YELLOW}; lxw_chart_fill fill = {.color = LXW_COLOR_RED, .transparency = 100}; diff --git a/test/functional/src/test_chart_format24.c b/test/functional/src/test_chart_format24.c index e44166cb..1e413347 100644 --- a/test/functional/src/test_chart_format24.c +++ b/test/functional/src/test_chart_format24.c @@ -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_fill fill1 = {.color = LXW_COLOR_YELLOW, .transparency = 75}; diff --git a/test/functional/src/test_chart_format25.c b/test/functional/src/test_chart_format25.c index 462c9a2b..e71d346f 100644 --- a/test/functional/src/test_chart_format25.c +++ b/test/functional/src/test_chart_format25.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_line line = {.color = LXW_COLOR_RED, .transparency = 50}; diff --git a/test/functional/src/test_chart_format26.c b/test/functional/src/test_chart_format26.c index cea96f7a..e32c0156 100644 --- a/test/functional/src/test_chart_format26.c +++ b/test/functional/src/test_chart_format26.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_trendline(series, LXW_CHART_TRENDLINE_TYPE_LINEAR, 0); chart_series_set_trendline_equation(series); diff --git a/test/functional/src/test_chart_format27.c b/test/functional/src/test_chart_format27.c index ed5b9aae..3cf56d57 100644 --- a/test/functional/src/test_chart_format27.c +++ b/test/functional/src/test_chart_format27.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_line line = {.color = LXW_COLOR_RED, .width = 1, diff --git a/test/functional/src/test_chart_format28.c b/test/functional/src/test_chart_format28.c index 14d314fa..a2cf84a6 100644 --- a/test/functional/src/test_chart_format28.c +++ b/test/functional/src/test_chart_format28.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_trendline(series, LXW_CHART_TRENDLINE_TYPE_LINEAR, 0); chart_series_set_trendline_equation(series); diff --git a/test/functional/src/test_chart_format29.c b/test/functional/src/test_chart_format29.c index 88f8504e..f2b03b1a 100644 --- a/test/functional/src/test_chart_format29.c +++ b/test/functional/src/test_chart_format29.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_line line = {.color = LXW_COLOR_RED, .width = 1, diff --git a/test/functional/src/test_chart_format30.c b/test/functional/src/test_chart_format30.c index 20b1cca1..8556b0ef 100644 --- a/test/functional/src/test_chart_format30.c +++ b/test/functional/src/test_chart_format30.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_trendline(series, LXW_CHART_TRENDLINE_TYPE_LINEAR, 0); chart_series_set_trendline_equation(series); diff --git a/test/functional/src/test_chart_format31.c b/test/functional/src/test_chart_format31.c index c129aa38..8b2dca2b 100644 --- a/test/functional/src/test_chart_format31.c +++ b/test/functional/src/test_chart_format31.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_line line = {.color = LXW_COLOR_RED, .width = 1, diff --git a/test/functional/src/test_chart_format32.c b/test/functional/src/test_chart_format32.c index 4f9a26df..2c452c6d 100644 --- a/test/functional/src/test_chart_format32.c +++ b/test/functional/src/test_chart_format32.c @@ -35,12 +35,12 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); lxw_chart_line line1 = {.width = 5}; lxw_chart_line line2 = {.width = 0.1}; diff --git a/test/functional/src/test_chart_gap01.c b/test/functional/src/test_chart_gap01.c index f95d0d7d..d33b6e05 100644 --- a/test/functional/src/test_chart_gap01.c +++ b/test/functional/src/test_chart_gap01.c @@ -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_set_series_overlap(chart, 5); chart_set_series_gap(chart, 157); diff --git a/test/functional/src/test_chart_gap02.c b/test/functional/src/test_chart_gap02.c index f1f1bd7f..20d87a6e 100644 --- a/test/functional/src/test_chart_gap02.c +++ b/test/functional/src/test_chart_gap02.c @@ -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_set_series_overlap(chart, -100); chart_set_series_gap(chart, 0); diff --git a/test/functional/src/test_chart_gap03.c b/test/functional/src/test_chart_gap03.c index 95c339e9..bf605ad5 100644 --- a/test/functional/src/test_chart_gap03.c +++ b/test/functional/src/test_chart_gap03.c @@ -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_set_series_overlap(chart, 100); chart_set_series_gap(chart, 500); diff --git a/test/functional/src/test_chart_gap04.c b/test/functional/src/test_chart_gap04.c new file mode 100644 index 00000000..0d208f7d --- /dev/null +++ b/test/functional/src/test_chart_gap04.c @@ -0,0 +1,48 @@ +/***************************************************************************** + * 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_gap04.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 45938176; + chart->axis_id_2 = 59715584; + chart->axis_id_3 = 62526208; + chart->axis_id_4 = 59718272; + + 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); + + /* Set gap and overlap for primary axis. */ + chart_set_series_gap(chart, 51); + chart_set_series_overlap(chart, 12); + + /* Set gap and overlap for secondary axis. */ + chart_set_series_gap_y2(chart, 251); + chart_set_series_overlap_y2(chart, -27); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gap05.c b/test/functional/src/test_chart_gap05.c new file mode 100644 index 00000000..0fec76a6 --- /dev/null +++ b/test/functional/src/test_chart_gap05.c @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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_gap05.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_BAR); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 45938176; + chart->axis_id_2 = 59715584; + chart->axis_id_3 = 70848512; + chart->axis_id_4 = 54519680; + + 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); + + /* Set gap and overlap for primary axis. */ + chart_set_series_gap(chart, 51); + chart_set_series_overlap(chart, 12); + + /* Set gap and overlap for secondary axis. */ + chart_set_series_gap_y2(chart, 251); + chart_set_series_overlap_y2(chart, -27); + + /* Set x2 axis label position to next_to. */ + chart_axis_set_label_position(chart->x2_axis, LXW_CHART_AXIS_LABEL_POSITION_NEXT_TO); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient01.c b/test/functional/src/test_chart_gradient01.c new file mode 100644 index 00000000..3d000056 --- /dev/null +++ b/test/functional/src/test_chart_gradient01.c @@ -0,0 +1,50 @@ +/***************************************************************************** + * 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_gradient01.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 61365248; + chart->axis_id_2 = 64275200; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 3, + }; + chart_series_set_gradient(series1, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient02.c b/test/functional/src/test_chart_gradient02.c new file mode 100644 index 00000000..d5d290ff --- /dev/null +++ b/test/functional/src/test_chart_gradient02.c @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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_gradient02.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 61363328; + chart->axis_id_2 = 61364864; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 3, + .angle = 30, + }; + chart_series_set_gradient(series1, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient03.c b/test/functional/src/test_chart_gradient03.c new file mode 100644 index 00000000..b945abff --- /dev/null +++ b/test/functional/src/test_chart_gradient03.c @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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_gradient03.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 61363712; + chart->axis_id_2 = 61365248; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 3, + .positions = {0, 40, 100}, + }; + chart_series_set_gradient(series1, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient04.c b/test/functional/src/test_chart_gradient04.c new file mode 100644 index 00000000..ffd888a9 --- /dev/null +++ b/test/functional/src/test_chart_gradient04.c @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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_gradient04.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 61363712; + chart->axis_id_2 = 61365248; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 3, + .type = LXW_CHART_GRADIENT_FILL_RADIAL, + }; + chart_series_set_gradient(series1, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient05.c b/test/functional/src/test_chart_gradient05.c new file mode 100644 index 00000000..e1cd859e --- /dev/null +++ b/test/functional/src/test_chart_gradient05.c @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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_gradient05.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 61363712; + chart->axis_id_2 = 61365248; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 3, + .type = LXW_CHART_GRADIENT_FILL_RECTANGULAR, + }; + chart_series_set_gradient(series1, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient06.c b/test/functional/src/test_chart_gradient06.c new file mode 100644 index 00000000..743c9df2 --- /dev/null +++ b/test/functional/src/test_chart_gradient06.c @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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_gradient06.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 61363328; + chart->axis_id_2 = 61364864; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 3, + .type = LXW_CHART_GRADIENT_FILL_PATH, + }; + chart_series_set_gradient(series1, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient07.c b/test/functional/src/test_chart_gradient07.c new file mode 100644 index 00000000..40bfdcc7 --- /dev/null +++ b/test/functional/src/test_chart_gradient07.c @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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_gradient07.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 68936064; + chart->axis_id_2 = 68937600; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 3, + }; + chart_series_set_gradient(series1, &gradient); + chart_series_set_invert_if_negative(series1); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient08.c b/test/functional/src/test_chart_gradient08.c new file mode 100644 index 00000000..d85166c1 --- /dev/null +++ b/test/functional/src/test_chart_gradient08.c @@ -0,0 +1,50 @@ +/***************************************************************************** + * 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_gradient08.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 69014272; + chart->axis_id_2 = 69016192; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + 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"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 3, + }; + chart_chartarea_set_gradient(chart, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient09.c b/test/functional/src/test_chart_gradient09.c new file mode 100644 index 00000000..fa007d64 --- /dev/null +++ b/test/functional/src/test_chart_gradient09.c @@ -0,0 +1,50 @@ +/***************************************************************************** + * 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_gradient09.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 56159616; + chart->axis_id_2 = 61364480; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + 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"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 3, + }; + chart_plotarea_set_gradient(chart, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient10.c b/test/functional/src/test_chart_gradient10.c new file mode 100644 index 00000000..28f36db7 --- /dev/null +++ b/test/functional/src/test_chart_gradient10.c @@ -0,0 +1,50 @@ +/***************************************************************************** + * 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_gradient10.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 56159232; + chart->axis_id_2 = 61364096; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x156B13}, + .num_stops = 2, + }; + chart_series_set_gradient(series1, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient11.c b/test/functional/src/test_chart_gradient11.c new file mode 100644 index 00000000..ed22cf31 --- /dev/null +++ b/test/functional/src/test_chart_gradient11.c @@ -0,0 +1,50 @@ +/***************************************************************************** + * 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_gradient11.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 66738048; + chart->axis_id_2 = 66748416; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 4, + }; + chart_series_set_gradient(series1, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient12.c b/test/functional/src/test_chart_gradient12.c new file mode 100644 index 00000000..86ac2175 --- /dev/null +++ b/test/functional/src/test_chart_gradient12.c @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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_gradient12.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 56159232; + chart->axis_id_2 = 61364096; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x156B13}, + .num_stops = 2, + .positions = {10, 90}, + }; + chart_series_set_gradient(series1, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gradient13.c b/test/functional/src/test_chart_gradient13.c new file mode 100644 index 00000000..49f73ff5 --- /dev/null +++ b/test/functional/src/test_chart_gradient13.c @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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_gradient13.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 56159232; + chart->axis_id_2 = 61364096; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_gradient_fill gradient = { + .colors = {0xDDEBCF, 0x9CB86E, 0x156B13}, + .num_stops = 3, + .angle = 355, + }; + chart_series_set_gradient(series1, &gradient); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_gridlines01.c b/test/functional/src/test_chart_gridlines01.c index 9948241e..256ede83 100644 --- a/test/functional/src/test_chart_gridlines01.c +++ b/test/functional/src/test_chart_gridlines01.c @@ -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_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); diff --git a/test/functional/src/test_chart_gridlines02.c b/test/functional/src/test_chart_gridlines02.c index 46c3d40d..4b47d8ba 100644 --- a/test/functional/src/test_chart_gridlines02.c +++ b/test/functional/src/test_chart_gridlines02.c @@ -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_major_gridlines_set_visible(chart->x_axis, LXW_TRUE); chart_axis_major_gridlines_set_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_gridlines04.c b/test/functional/src/test_chart_gridlines04.c index 513510e4..5c419f9f 100644 --- a/test/functional/src/test_chart_gridlines04.c +++ b/test/functional/src/test_chart_gridlines04.c @@ -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_major_gridlines_set_visible(chart->y_axis, LXW_FALSE); diff --git a/test/functional/src/test_chart_gridlines05.c b/test/functional/src/test_chart_gridlines05.c index c201d80f..76d5ceee 100644 --- a/test/functional/src/test_chart_gridlines05.c +++ b/test/functional/src/test_chart_gridlines05.c @@ -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_major_gridlines_set_visible(chart->x_axis, LXW_TRUE); diff --git a/test/functional/src/test_chart_gridlines06.c b/test/functional/src/test_chart_gridlines06.c index 9117adbf..97e02929 100644 --- a/test/functional/src/test_chart_gridlines06.c +++ b/test/functional/src/test_chart_gridlines06.c @@ -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_major_gridlines_set_visible(chart->x_axis, LXW_TRUE); chart_axis_minor_gridlines_set_visible(chart->x_axis, LXW_TRUE); diff --git a/test/functional/src/test_chart_gridlines08.c b/test/functional/src/test_chart_gridlines08.c index 4c3e643a..d9650e2f 100644 --- a/test/functional/src/test_chart_gridlines08.c +++ b/test/functional/src/test_chart_gridlines08.c @@ -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_major_gridlines_set_visible(chart->y_axis, LXW_TRUE); chart_axis_minor_gridlines_set_visible(chart->y_axis, LXW_TRUE); diff --git a/test/functional/src/test_chart_gridlines09.c b/test/functional/src/test_chart_gridlines09.c index e75f5784..65f57bdc 100644 --- a/test/functional/src/test_chart_gridlines09.c +++ b/test/functional/src/test_chart_gridlines09.c @@ -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_line line1 = {.color = LXW_COLOR_RED, diff --git a/test/functional/src/test_chart_high_low_lines01.c b/test/functional/src/test_chart_high_low_lines01.c index 57c15ccd..96cb0d0a 100644 --- a/test/functional/src/test_chart_high_low_lines01.c +++ b/test/functional/src/test_chart_high_low_lines01.c @@ -38,12 +38,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); diff --git a/test/functional/src/test_chart_high_low_lines02.c b/test/functional/src/test_chart_high_low_lines02.c index 527e9a6d..26ddf2b0 100644 --- a/test/functional/src/test_chart_high_low_lines02.c +++ b/test/functional/src/test_chart_high_low_lines02.c @@ -41,12 +41,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); diff --git a/test/functional/src/test_chart_layout01.c b/test/functional/src/test_chart_layout01.c index 2d65c7ac..9653ec89 100644 --- a/test/functional/src/test_chart_layout01.c +++ b/test/functional/src/test_chart_layout01.c @@ -32,9 +32,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_layout layout = { .x = 0.13171062992125, diff --git a/test/functional/src/test_chart_layout02.c b/test/functional/src/test_chart_layout02.c index d245bd41..6399307e 100644 --- a/test/functional/src/test_chart_layout02.c +++ b/test/functional/src/test_chart_layout02.c @@ -32,9 +32,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_layout layout = { .x = 0.80197353455818, diff --git a/test/functional/src/test_chart_layout03.c b/test/functional/src/test_chart_layout03.c index 3d2e3b96..aae2160b 100644 --- a/test/functional/src/test_chart_layout03.c +++ b/test/functional/src/test_chart_layout03.c @@ -32,9 +32,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_layout layout = { .x = 0.80197353455818, diff --git a/test/functional/src/test_chart_layout04.c b/test/functional/src/test_chart_layout04.c index 02ae3988..d822fea2 100644 --- a/test/functional/src/test_chart_layout04.c +++ b/test/functional/src/test_chart_layout04.c @@ -32,9 +32,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_layout layout = { diff --git a/test/functional/src/test_chart_layout05.c b/test/functional/src/test_chart_layout05.c index 5e4ea98d..400b3f0e 100644 --- a/test/functional/src/test_chart_layout05.c +++ b/test/functional/src/test_chart_layout05.c @@ -35,12 +35,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); diff --git a/test/functional/src/test_chart_layout06.c b/test/functional/src/test_chart_layout06.c index a838e091..6587d920 100644 --- a/test/functional/src/test_chart_layout06.c +++ b/test/functional/src/test_chart_layout06.c @@ -32,9 +32,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_layout layout = { diff --git a/test/functional/src/test_chart_layout07.c b/test/functional/src/test_chart_layout07.c index 21673c4e..5bda8e88 100644 --- a/test/functional/src/test_chart_layout07.c +++ b/test/functional/src/test_chart_layout07.c @@ -32,9 +32,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_layout layout = { .x = 0.359652668416448, diff --git a/test/functional/src/test_chart_layout08.c b/test/functional/src/test_chart_layout08.c index 2f73b41e..f402d62f 100644 --- a/test/functional/src/test_chart_layout08.c +++ b/test/functional/src/test_chart_layout08.c @@ -32,9 +32,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_layout layout = { .x = 0.359652668416448, diff --git a/test/functional/src/test_chart_legend01.c b/test/functional/src/test_chart_legend01.c index 447fad3d..dddeb12c 100644 --- a/test/functional/src/test_chart_legend01.c +++ b/test/functional/src/test_chart_legend01.c @@ -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_legend_set_position(chart, LXW_CHART_LEGEND_NONE); diff --git a/test/functional/src/test_chart_legend03.c b/test/functional/src/test_chart_legend03.c index 23c82a46..01eef032 100644 --- a/test/functional/src/test_chart_legend03.c +++ b/test/functional/src/test_chart_legend03.c @@ -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_legend_set_position(chart, LXW_CHART_LEGEND_TOP_RIGHT); diff --git a/test/functional/src/test_chart_legend04.c b/test/functional/src/test_chart_legend04.c index 01bb0e56..4f3f792e 100644 --- a/test/functional/src/test_chart_legend04.c +++ b/test/functional/src/test_chart_legend04.c @@ -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_legend_set_position(chart, LXW_CHART_LEGEND_OVERLAY_TOP_RIGHT); diff --git a/test/functional/src/test_chart_line01.c b/test/functional/src/test_chart_line01.c index cf3297d0..36fabf18 100644 --- a/test/functional/src/test_chart_line01.c +++ b/test/functional/src/test_chart_line01.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_line02.c b/test/functional/src/test_chart_line02.c new file mode 100644 index 00000000..c74b8003 --- /dev/null +++ b/test/functional/src/test_chart_line02.c @@ -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_line02.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 63593856; + chart->axis_id_2 = 63612032; + chart->axis_id_3 = 63615360; + chart->axis_id_4 = 63613568; + + 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); +} diff --git a/test/functional/src/test_chart_line03.c b/test/functional/src/test_chart_line03.c index 603d6145..84e4ed1d 100644 --- a/test/functional/src/test_chart_line03.c +++ b/test/functional/src/test_chart_line03.c @@ -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_smooth(series, LXW_TRUE); diff --git a/test/functional/src/test_chart_line04.c b/test/functional/src/test_chart_line04.c index b9ffacab..550edc63 100644 --- a/test/functional/src/test_chart_line04.c +++ b/test/functional/src/test_chart_line04.c @@ -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 *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); - chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5", 0); chart_series_set_smooth(series1, LXW_TRUE); chart_series_set_smooth(series3, LXW_TRUE); diff --git a/test/functional/src/test_chart_line05.c b/test/functional/src/test_chart_line05.c index 9dd17a31..e563f3a1 100644 --- a/test/functional/src/test_chart_line05.c +++ b/test/functional/src/test_chart_line05.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_line06.c b/test/functional/src/test_chart_line06.c index f27cd362..66864cd2 100644 --- a/test/functional/src/test_chart_line06.c +++ b/test/functional/src/test_chart_line06.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_line07.c b/test/functional/src/test_chart_line07.c new file mode 100644 index 00000000..038db048 --- /dev/null +++ b/test/functional/src/test_chart_line07.c @@ -0,0 +1,58 @@ +/***************************************************************************** + * 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_line07.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 77034624; + chart->axis_id_2 = 77036544; + chart->axis_id_3 = 95388032; + chart->axis_id_4 = 103040896; + + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {10, 40, 50, 20, 10}; + uint8_t data3[7] = {1, 2, 3, 4, 5, 6, 7}; + uint8_t data4[7] = {30, 10, 20, 40, 30, 10, 20}; + + 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); + } + for (row = 0; row < 7; row++) { + worksheet_write_number(worksheet, row, 2, data3[row], NULL); + worksheet_write_number(worksheet, row, 3, data4[row], NULL); + } + + /* Add series to primary axis. */ + chart_add_series(chart, + "=Sheet1!$A$1:$A$5", + "=Sheet1!$B$1:$B$5", + 0); + + /* Add series to secondary axis. */ + chart_add_series(chart, + "=Sheet1!$C$1:$C$7", + "=Sheet1!$D$1:$D$7", + 1); + + /* Configure secondary X axis to show labels. */ + chart_axis_set_label_position(chart->x2_axis, LXW_CHART_AXIS_LABEL_POSITION_NEXT_TO); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_line08.c b/test/functional/src/test_chart_line08.c new file mode 100644 index 00000000..22aec7c7 --- /dev/null +++ b/test/functional/src/test_chart_line08.c @@ -0,0 +1,63 @@ +/***************************************************************************** + * 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_line08.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 77034624; + chart->axis_id_2 = 77036544; + chart->axis_id_3 = 95388032; + chart->axis_id_4 = 103040896; + + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {10, 40, 50, 20, 10}; + uint8_t data3[7] = {1, 2, 3, 4, 5, 6, 7}; + uint8_t data4[7] = {30, 10, 20, 40, 30, 10, 20}; + + 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); + } + for (row = 0; row < 7; row++) { + worksheet_write_number(worksheet, row, 2, data3[row], NULL); + worksheet_write_number(worksheet, row, 3, data4[row], NULL); + } + + /* Add series to primary axis. */ + chart_add_series(chart, + "=Sheet1!$A$1:$A$5", + "=Sheet1!$B$1:$B$5", + 0); + + /* Add series to secondary axis. */ + chart_add_series(chart, + "=Sheet1!$C$1:$C$7", + "=Sheet1!$D$1:$D$7", + 1); + + /* Configure secondary X axis: visible, with labels, at top. */ + chart->x2_axis->hidden = LXW_FALSE; + chart_axis_set_label_position(chart->x2_axis, LXW_CHART_AXIS_LABEL_POSITION_NEXT_TO); + chart->x2_axis->axis_position = LXW_CHART_AXIS_TOP; + + /* Configure secondary Y axis: crossing at max. */ + chart_axis_set_crossing_max(chart->y2_axis); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_order01.c b/test/functional/src/test_chart_order01.c index 8cf88ba4..1c4999eb 100644 --- a/test/functional/src/test_chart_order01.c +++ b/test/functional/src/test_chart_order01.c @@ -50,10 +50,10 @@ int main() { worksheet_write_number(worksheet3, row, col, data[row][col], NULL); } - chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5"); - chart_add_series(chart2, NULL, "=Sheet2!$A$1:$A$5"); - chart_add_series(chart3, NULL, "=Sheet3!$A$1:$A$5"); - chart_add_series(chart4, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5", 0); + chart_add_series(chart2, NULL, "=Sheet2!$A$1:$A$5", 0); + chart_add_series(chart3, NULL, "=Sheet3!$A$1:$A$5", 0); + chart_add_series(chart4, NULL, "=Sheet1!$B$1:$B$5", 0); worksheet_insert_chart(worksheet1, CELL("E9"), chart1); worksheet_insert_chart(worksheet2, CELL("E9"), chart2); diff --git a/test/functional/src/test_chart_order02.c b/test/functional/src/test_chart_order02.c index e70033c2..3b2ea2b9 100644 --- a/test/functional/src/test_chart_order02.c +++ b/test/functional/src/test_chart_order02.c @@ -50,10 +50,10 @@ int main() { worksheet_write_number(worksheet3, row, col, data[row][col], NULL); } - chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5"); - chart_add_series(chart2, NULL, "=Sheet2!$A$1:$A$5"); - chart_add_series(chart3, NULL, "=Sheet3!$A$1:$A$5"); - chart_add_series(chart4, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart1, NULL, "=Sheet1!$A$1:$A$5", 0); + chart_add_series(chart2, NULL, "=Sheet2!$A$1:$A$5", 0); + chart_add_series(chart3, NULL, "=Sheet3!$A$1:$A$5", 0); + chart_add_series(chart4, NULL, "=Sheet1!$B$1:$B$5", 0); worksheet_insert_chart(worksheet1, CELL("E9"), chart1); worksheet_insert_chart(worksheet2, CELL("E9"), chart2); diff --git a/test/functional/src/test_chart_pattern01.c b/test/functional/src/test_chart_pattern01.c index ae5eccf0..6f127b3b 100644 --- a/test/functional/src/test_chart_pattern01.c +++ b/test/functional/src/test_chart_pattern01.c @@ -31,14 +31,14 @@ int main() { for (col = 0; col < 8; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); - chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3"); - chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3"); - chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3"); - chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3"); - chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3"); - chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_pattern02.c b/test/functional/src/test_chart_pattern02.c index c419b0ea..3f4a6cf6 100644 --- a/test/functional/src/test_chart_pattern02.c +++ b/test/functional/src/test_chart_pattern02.c @@ -31,14 +31,14 @@ int main() { for (col = 0; col < 8; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3"); - lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3"); - lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3"); - lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3"); - lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3"); - lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3", 0); + lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3", 0); + lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3", 0); + lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3", 0); + lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3", 0); + lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3", 0); lxw_chart_pattern pattern1 = {.type = LXW_CHART_PATTERN_PERCENT_5, .fg_color = 0xC00000, diff --git a/test/functional/src/test_chart_pattern03.c b/test/functional/src/test_chart_pattern03.c index 3f759128..aac6039f 100644 --- a/test/functional/src/test_chart_pattern03.c +++ b/test/functional/src/test_chart_pattern03.c @@ -31,14 +31,14 @@ int main() { for (col = 0; col < 8; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3"); - lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3"); - lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3"); - lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3"); - lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3"); - lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3", 0); + lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3", 0); + lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3", 0); + lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3", 0); + lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3", 0); + lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3", 0); lxw_chart_pattern pattern1 = {.type = LXW_CHART_PATTERN_PERCENT_10, .fg_color = 0xC00000, diff --git a/test/functional/src/test_chart_pattern04.c b/test/functional/src/test_chart_pattern04.c index 74302768..023449ac 100644 --- a/test/functional/src/test_chart_pattern04.c +++ b/test/functional/src/test_chart_pattern04.c @@ -31,14 +31,14 @@ int main() { for (col = 0; col < 8; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3"); - lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3"); - lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3"); - lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3"); - lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3"); - lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3", 0); + lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3", 0); + lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3", 0); + lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3", 0); + lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3", 0); + lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3", 0); lxw_chart_pattern pattern1 = {.type = LXW_CHART_PATTERN_PERCENT_20, .fg_color = 0xC00000, diff --git a/test/functional/src/test_chart_pattern05.c b/test/functional/src/test_chart_pattern05.c index bd0e8259..1c80d56d 100644 --- a/test/functional/src/test_chart_pattern05.c +++ b/test/functional/src/test_chart_pattern05.c @@ -31,14 +31,14 @@ int main() { for (col = 0; col < 8; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3"); - lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3"); - lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3"); - lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3"); - lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3"); - lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3", 0); + lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3", 0); + lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3", 0); + lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3", 0); + lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3", 0); + lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3", 0); lxw_chart_pattern pattern1 = {.type = LXW_CHART_PATTERN_PERCENT_25, .fg_color = 0xC00000, diff --git a/test/functional/src/test_chart_pattern06.c b/test/functional/src/test_chart_pattern06.c index 475c0c9c..eeb70ec1 100644 --- a/test/functional/src/test_chart_pattern06.c +++ b/test/functional/src/test_chart_pattern06.c @@ -31,14 +31,14 @@ int main() { for (col = 0; col < 8; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3"); - lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3"); - lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3"); - lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3"); - lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3"); - lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3", 0); + lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3", 0); + lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3", 0); + lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3", 0); + lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3", 0); + lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3", 0); lxw_chart_pattern pattern1 = {.type = LXW_CHART_PATTERN_PERCENT_30, .fg_color = 0xC00000, diff --git a/test/functional/src/test_chart_pattern07.c b/test/functional/src/test_chart_pattern07.c index 77a13b35..d629f43e 100644 --- a/test/functional/src/test_chart_pattern07.c +++ b/test/functional/src/test_chart_pattern07.c @@ -31,14 +31,14 @@ int main() { for (col = 0; col < 8; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3"); - lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3"); - lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3"); - lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3"); - lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3"); - lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3", 0); + lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3", 0); + lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3", 0); + lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3", 0); + lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3", 0); + lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3", 0); lxw_chart_pattern pattern1 = {.type = LXW_CHART_PATTERN_PERCENT_40, .fg_color = 0xC00000, diff --git a/test/functional/src/test_chart_pattern08.c b/test/functional/src/test_chart_pattern08.c index 1573ae84..9978a7d5 100644 --- a/test/functional/src/test_chart_pattern08.c +++ b/test/functional/src/test_chart_pattern08.c @@ -31,14 +31,14 @@ int main() { for (col = 0; col < 8; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); - lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3"); - lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3"); - lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3"); - lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3"); - lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3"); - lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3"); - lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3"); + lxw_chart_series *series1 = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3", 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3", 0); + lxw_chart_series *series4 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3", 0); + lxw_chart_series *series5 = chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3", 0); + lxw_chart_series *series6 = chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3", 0); + lxw_chart_series *series7 = chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3", 0); + lxw_chart_series *series8 = chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3", 0); lxw_chart_pattern pattern1 = {.type = LXW_CHART_PATTERN_PERCENT_5, .fg_color = LXW_COLOR_YELLOW, diff --git a/test/functional/src/test_chart_pattern10.c b/test/functional/src/test_chart_pattern10.c index 17508bbb..31a3a05d 100644 --- a/test/functional/src/test_chart_pattern10.c +++ b/test/functional/src/test_chart_pattern10.c @@ -31,14 +31,14 @@ int main() { for (col = 0; col < 8; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); - chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3"); - chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3"); - chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3"); - chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3"); - chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3"); - chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3"); - chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$E$1:$E$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$F$1:$F$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$G$1:$G$3", 0); + chart_add_series(chart, NULL, "=Sheet1!$H$1:$H$3", 0); lxw_chart_pattern pattern = {.type = LXW_CHART_PATTERN_PERCENT_5, .fg_color = LXW_COLOR_RED, diff --git a/test/functional/src/test_chart_pie01.c b/test/functional/src/test_chart_pie01.c index c1da50b8..cbcf16c9 100644 --- a/test/functional/src/test_chart_pie01.c +++ b/test/functional/src/test_chart_pie01.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_pie02.c b/test/functional/src/test_chart_pie02.c index f331364a..bfce748d 100644 --- a/test/functional/src/test_chart_pie02.c +++ b/test/functional/src/test_chart_pie02.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); lxw_chart_font font1 = {.bold = LXW_TRUE, .italic = LXW_TRUE, .baseline = -1}; chart_legend_set_font(chart, &font1); diff --git a/test/functional/src/test_chart_pie03.c b/test/functional/src/test_chart_pie03.c index 77faf9e6..396460a6 100644 --- a/test/functional/src/test_chart_pie03.c +++ b/test/functional/src/test_chart_pie03.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); int16_t series[] = {1, -1}; chart_legend_delete_series(chart, series); diff --git a/test/functional/src/test_chart_pie04.c b/test/functional/src/test_chart_pie04.c index ead03541..234e1886 100644 --- a/test/functional/src/test_chart_pie04.c +++ b/test/functional/src/test_chart_pie04.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); chart_legend_set_position(chart, LXW_CHART_LEGEND_OVERLAY_RIGHT); diff --git a/test/functional/src/test_chart_pie05.c b/test/functional/src/test_chart_pie05.c index 04370f43..620a5aa2 100644 --- a/test/functional/src/test_chart_pie05.c +++ b/test/functional/src/test_chart_pie05.c @@ -30,7 +30,7 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$3", "=Sheet1!$B$1:$B$3" - ); + , 0); chart_set_rotation(chart, 45); diff --git a/test/functional/src/test_chart_points01.c b/test/functional/src/test_chart_points01.c index ee1c84d8..82d4ec7b 100644 --- a/test/functional/src/test_chart_points01.c +++ b/test/functional/src/test_chart_points01.c @@ -23,7 +23,7 @@ int main() { worksheet_write_number(worksheet, 4, 0, 7, NULL); worksheet_write_number(worksheet, 5, 0, 4, NULL); - lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$6"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$6", 0); lxw_chart_fill fill1 = {.color = LXW_COLOR_RED}; diff --git a/test/functional/src/test_chart_points02.c b/test/functional/src/test_chart_points02.c index 88120d30..acb48029 100644 --- a/test/functional/src/test_chart_points02.c +++ b/test/functional/src/test_chart_points02.c @@ -23,7 +23,7 @@ int main() { worksheet_write_number(worksheet, 4, 0, 7, NULL); worksheet_write_number(worksheet, 5, 0, 4, NULL); - lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$6"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$6", 0); lxw_chart_line line1 = {.color = LXW_COLOR_RED, .dash_type = LXW_CHART_LINE_DASH_SQUARE_DOT}; diff --git a/test/functional/src/test_chart_points03.c b/test/functional/src/test_chart_points03.c index 8143c710..c565dee8 100644 --- a/test/functional/src/test_chart_points03.c +++ b/test/functional/src/test_chart_points03.c @@ -21,7 +21,7 @@ int main() { worksheet_write_number(worksheet, 1, 0, 5, NULL); worksheet_write_number(worksheet, 2, 0, 4, NULL); - lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3"); + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$3", 0); lxw_chart_fill fill1 = {.color = 0xFF0000}; diff --git a/test/functional/src/test_chart_points04.c b/test/functional/src/test_chart_points04.c index 5e2de257..c09d3f46 100644 --- a/test/functional/src/test_chart_points04.c +++ b/test/functional/src/test_chart_points04.c @@ -36,11 +36,11 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", - "=Sheet1!$C$1:$C$5"); + "=Sheet1!$C$1:$C$5", 0); lxw_chart_fill red_fill = {.color = LXW_COLOR_RED}; lxw_chart_fill yellow_fill = {.color = LXW_COLOR_YELLOW}; diff --git a/test/functional/src/test_chart_points05.c b/test/functional/src/test_chart_points05.c index db65d9fd..9aadc21a 100644 --- a/test/functional/src/test_chart_points05.c +++ b/test/functional/src/test_chart_points05.c @@ -36,11 +36,11 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", - "=Sheet1!$C$1:$C$5"); + "=Sheet1!$C$1:$C$5", 0); lxw_chart_fill red_fill = {.color = LXW_COLOR_RED}; lxw_chart_point red_point = {.fill = &red_fill}; diff --git a/test/functional/src/test_chart_points06.c b/test/functional/src/test_chart_points06.c index 1effc16f..8ae53e13 100644 --- a/test/functional/src/test_chart_points06.c +++ b/test/functional/src/test_chart_points06.c @@ -36,11 +36,11 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", - "=Sheet1!$C$1:$C$5"); + "=Sheet1!$C$1:$C$5", 0); lxw_chart_fill red_fill = {.color = LXW_COLOR_RED}; lxw_chart_point red_point = {.fill = &red_fill}; diff --git a/test/functional/src/test_chart_radar01.c b/test/functional/src/test_chart_radar01.c index 78826eb9..51b33667 100644 --- a/test/functional/src/test_chart_radar01.c +++ b/test/functional/src/test_chart_radar01.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_radar02.c b/test/functional/src/test_chart_radar02.c index aa25d691..b56c8fed 100644 --- a/test/functional/src/test_chart_radar02.c +++ b/test/functional/src/test_chart_radar02.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_radar03.c b/test/functional/src/test_chart_radar03.c index 1899ce95..b9832009 100644 --- a/test/functional/src/test_chart_radar03.c +++ b/test/functional/src/test_chart_radar03.c @@ -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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_scatter01.c b/test/functional/src/test_chart_scatter01.c index 8efc69f9..8de72d41 100644 --- a/test/functional/src/test_chart_scatter01.c +++ b/test/functional/src/test_chart_scatter01.c @@ -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); return workbook_close(workbook); diff --git a/test/functional/src/test_chart_scatter02.c b/test/functional/src/test_chart_scatter02.c index 069a0ff6..a940f201 100644 --- a/test/functional/src/test_chart_scatter02.c +++ b/test/functional/src/test_chart_scatter02.c @@ -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); diff --git a/test/functional/src/test_chart_scatter03.c b/test/functional/src/test_chart_scatter03.c index ffbff612..c451bc8a 100644 --- a/test/functional/src/test_chart_scatter03.c +++ b/test/functional/src/test_chart_scatter03.c @@ -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); diff --git a/test/functional/src/test_chart_scatter04.c b/test/functional/src/test_chart_scatter04.c index eb5a28e3..84e568ee 100644 --- a/test/functional/src/test_chart_scatter04.c +++ b/test/functional/src/test_chart_scatter04.c @@ -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); diff --git a/test/functional/src/test_chart_scatter05.c b/test/functional/src/test_chart_scatter05.c index 8256feeb..74227e85 100644 --- a/test/functional/src/test_chart_scatter05.c +++ b/test/functional/src/test_chart_scatter05.c @@ -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); diff --git a/test/functional/src/test_chart_scatter06.c b/test/functional/src/test_chart_scatter06.c index a6d3034e..cd66b94f 100644 --- a/test/functional/src/test_chart_scatter06.c +++ b/test/functional/src/test_chart_scatter06.c @@ -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_major_unit(chart->x_axis, 3); chart_axis_set_minor_unit(chart->x_axis, 1); diff --git a/test/functional/src/test_chart_scatter07.c b/test/functional/src/test_chart_scatter07.c new file mode 100644 index 00000000..f421024a --- /dev/null +++ b/test/functional/src/test_chart_scatter07.c @@ -0,0 +1,44 @@ +/***************************************************************************** + * 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_scatter07.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_SCATTER); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 63597952; + chart->axis_id_2 = 63616128; + chart->axis_id_3 = 63617664; + chart->axis_id_4 = 63619456; + + uint8_t data1[5] = {27, 33, 44, 12, 1}; + uint8_t data2[5] = {6, 8, 6, 4, 2}; + uint8_t data3[5] = {20, 10, 30, 50, 40}; + uint8_t data4[5] = {0, 27, 23, 30, 40}; + + 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); + worksheet_write_number(worksheet, row, 2, data3[row], NULL); + worksheet_write_number(worksheet, row, 3, data4[row], NULL); + } + + chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, "=Sheet1!$C$1:$C$5", "=Sheet1!$D$1:$D$5", 1); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_scatter09.c b/test/functional/src/test_chart_scatter09.c index 38eb0e0d..64e6d225 100644 --- a/test/functional/src/test_chart_scatter09.c +++ b/test/functional/src/test_chart_scatter09.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_smooth(series, LXW_FALSE); diff --git a/test/functional/src/test_chart_scatter10.c b/test/functional/src/test_chart_scatter10.c index eaae9483..79d344db 100644 --- a/test/functional/src/test_chart_scatter10.c +++ b/test/functional/src/test_chart_scatter10.c @@ -36,12 +36,12 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); chart_series_set_smooth(series, LXW_FALSE); diff --git a/test/functional/src/test_chart_scatter11.c b/test/functional/src/test_chart_scatter11.c index 3c2a520b..297855d6 100644 --- a/test/functional/src/test_chart_scatter11.c +++ b/test/functional/src/test_chart_scatter11.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series = 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_series_set_smooth(series, LXW_TRUE); diff --git a/test/functional/src/test_chart_scatter12.c b/test/functional/src/test_chart_scatter12.c index 14c274f0..a8854134 100644 --- a/test/functional/src/test_chart_scatter12.c +++ b/test/functional/src/test_chart_scatter12.c @@ -36,12 +36,12 @@ int main() { lxw_chart_series *series1 = 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_series_set_marker_type(series1, LXW_CHART_MARKER_AUTOMATIC); diff --git a/test/functional/src/test_chart_scatter13.c b/test/functional/src/test_chart_scatter13.c index ab5eb169..20445834 100644 --- a/test/functional/src/test_chart_scatter13.c +++ b/test/functional/src/test_chart_scatter13.c @@ -36,12 +36,12 @@ int main() { chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); chart_series_set_marker_type(series2, LXW_CHART_MARKER_NONE); diff --git a/test/functional/src/test_chart_scatter14.c b/test/functional/src/test_chart_scatter14.c index 63b18853..f5dd97fc 100644 --- a/test/functional/src/test_chart_scatter14.c +++ b/test/functional/src/test_chart_scatter14.c @@ -37,12 +37,12 @@ int main() { lxw_chart_series *series1 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5" - ); + , 0); lxw_chart_series *series2 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5" - ); + , 0); chart_series_set_marker_type(series1, LXW_CHART_MARKER_STAR); diff --git a/test/functional/src/test_chart_scatter15.c b/test/functional/src/test_chart_scatter15.c index 4d6e6bf1..57f72ae3 100644 --- a/test/functional/src/test_chart_scatter15.c +++ b/test/functional/src/test_chart_scatter15.c @@ -28,7 +28,7 @@ int main() { worksheet_write_number(worksheet, 2, 0, 3, NULL); worksheet_write_number(worksheet, 2, 1, 30, NULL); - chart_add_series(chart, "=Sheet1!$A$2:$A$3", "=Sheet1!$B$2:$B$3"); + chart_add_series(chart, "=Sheet1!$A$2:$A$3", "=Sheet1!$B$2:$B$3", 0); lxw_chart_font font1 = {.italic = LXW_TRUE, .baseline = -1}; chart_axis_set_name_range(chart->x_axis, "Sheet1", 0, 0); diff --git a/test/functional/src/test_chart_size01.c b/test/functional/src/test_chart_size01.c index af0eb082..4b85900d 100644 --- a/test/functional/src/test_chart_size01.c +++ b/test/functional/src/test_chart_size01.c @@ -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_options options = {.x_scale = 1.06666667, .y_scale = 1.11111112}; worksheet_insert_chart_opt(worksheet, CELL("E9"), chart, &options); diff --git a/test/functional/src/test_chart_size04.c b/test/functional/src/test_chart_size04.c index 520c8abd..60865872 100644 --- a/test/functional/src/test_chart_size04.c +++ b/test/functional/src/test_chart_size04.c @@ -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_options options = {.x_offset = 8, .y_offset = 9}; worksheet_insert_chart_opt(worksheet, CELL("E9"), chart, &options); diff --git a/test/functional/src/test_chart_sparse01.c b/test/functional/src/test_chart_sparse01.c index d019fc0c..53dd3b82 100644 --- a/test/functional/src/test_chart_sparse01.c +++ b/test/functional/src/test_chart_sparse01.c @@ -43,12 +43,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$6", /* Ranges exceeds the data. */ "=Sheet1!$C$1:$C$6" - ); + , 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); return workbook_close(workbook); diff --git a/test/functional/src/test_chart_stock01.c b/test/functional/src/test_chart_stock01.c new file mode 100644 index 00000000..96a11fda --- /dev/null +++ b/test/functional/src/test_chart_stock01.c @@ -0,0 +1,52 @@ +/***************************************************************************** + * 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_stock01.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_STOCK); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 40522880; + chart->axis_id_2 = 40524416; + + lxw_format *date_format = workbook_add_format(workbook); + format_set_num_format_index(date_format, 14); + + /* Dates as Excel serial numbers. */ + double dates[5] = {39083, 39084, 39085, 39086, 39087}; + /* High values. */ + double high[5] = {27.2, 25.03, 19.05, 20.34, 18.5}; + /* Low values. */ + double low[5] = {23.49, 19.55, 15.12, 17.84, 16.34}; + /* Close values. */ + double close[5] = {25.45, 23.05, 17.32, 20.45, 17.34}; + + int row; + for (row = 0; row < 5; row++) { + worksheet_write_number(worksheet, row, 0, dates[row], date_format); + worksheet_write_number(worksheet, row, 1, high[row], NULL); + worksheet_write_number(worksheet, row, 2, low[row], NULL); + worksheet_write_number(worksheet, row, 3, close[row], NULL); + } + + worksheet_set_column(worksheet, COLS("A:D"), 11, NULL); + + 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_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$D$1:$D$5", 0); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_stock02.c b/test/functional/src/test_chart_stock02.c new file mode 100644 index 00000000..36c91b18 --- /dev/null +++ b/test/functional/src/test_chart_stock02.c @@ -0,0 +1,54 @@ +/***************************************************************************** + * 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_stock02.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_STOCK); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 63596416; + chart->axis_id_2 = 63597952; + chart->axis_id_3 = 51206784; + chart->axis_id_4 = 51204480; + + lxw_format *date_format = workbook_add_format(workbook); + format_set_num_format_index(date_format, 14); + + /* Dates as Excel serial numbers. */ + double dates[5] = {39083, 39084, 39085, 39086, 39087}; + /* High values. */ + double high[5] = {27.2, 25.03, 19.05, 20.34, 18.5}; + /* Low values. */ + double low[5] = {23.49, 19.55, 15.12, 17.84, 16.34}; + /* Close values. */ + double close[5] = {25.45, 23.05, 17.32, 20.45, 17.34}; + + int row; + for (row = 0; row < 5; row++) { + worksheet_write_number(worksheet, row, 0, dates[row], date_format); + worksheet_write_number(worksheet, row, 1, high[row], NULL); + worksheet_write_number(worksheet, row, 2, low[row], NULL); + worksheet_write_number(worksheet, row, 3, close[row], NULL); + } + + worksheet_set_column(worksheet, COLS("A:D"), 11, NULL); + + 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_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$D$1:$D$5", 1); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_stock03.c b/test/functional/src/test_chart_stock03.c new file mode 100644 index 00000000..8066cb6e --- /dev/null +++ b/test/functional/src/test_chart_stock03.c @@ -0,0 +1,74 @@ +/***************************************************************************** + * 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_stock03.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_STOCK); + lxw_chart_series *series; + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 53202304; + chart->axis_id_2 = 66693376; + + lxw_format *date_format = workbook_add_format(workbook); + format_set_num_format_index(date_format, 14); + + /* Dates as Excel serial numbers. */ + double dates[5] = {39083, 39084, 39085, 39086, 39087}; + /* Open values. */ + double open[5] = {23.49, 19.55, 15.12, 17.84, 16.34}; + /* High values. */ + double high[5] = {27.2, 25.03, 19.05, 20.34, 18.5}; + /* Low values. */ + double low[5] = {23.49, 19.55, 15.12, 17.84, 16.34}; + /* Close values. */ + double close[5] = {25.45, 23.05, 17.32, 20.45, 17.34}; + + int row; + for (row = 0; row < 5; row++) { + worksheet_write_number(worksheet, row, 0, dates[row], date_format); + worksheet_write_number(worksheet, row, 1, open[row], NULL); + worksheet_write_number(worksheet, row, 2, high[row], NULL); + worksheet_write_number(worksheet, row, 3, low[row], NULL); + worksheet_write_number(worksheet, row, 4, close[row], NULL); + } + + worksheet_set_column(worksheet, COLS("A:E"), 11, NULL); + + /* Line format hidden, marker none - like Rust test. */ + lxw_chart_line line = {.width = 2.25, .none = LXW_TRUE}; + + series = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5", 0); + chart_series_set_line(series, &line); + chart_series_set_marker_type(series, LXW_CHART_MARKER_NONE); + + series = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$C$1:$C$5", 0); + chart_series_set_line(series, &line); + chart_series_set_marker_type(series, LXW_CHART_MARKER_NONE); + + series = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$D$1:$D$5", 0); + chart_series_set_line(series, &line); + chart_series_set_marker_type(series, LXW_CHART_MARKER_NONE); + + series = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$E$1:$E$5", 0); + chart_series_set_line(series, &line); + chart_series_set_marker_type(series, LXW_CHART_MARKER_NONE); + + chart_set_high_low_lines(chart, NULL); + chart_set_up_down_bars(chart); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_str01.c b/test/functional/src/test_chart_str01.c index c1233fca..d5016b1f 100644 --- a/test/functional/src/test_chart_str01.c +++ b/test/functional/src/test_chart_str01.c @@ -40,9 +40,9 @@ int main() { worksheet_write_string(worksheet, CELL("A6"), "Foo" , 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); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_chart_str02.c b/test/functional/src/test_chart_str02.c index 6c544a2c..586657db 100644 --- a/test/functional/src/test_chart_str02.c +++ b/test/functional/src/test_chart_str02.c @@ -41,12 +41,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); return workbook_close(workbook); diff --git a/test/functional/src/test_chart_table01.c b/test/functional/src/test_chart_table01.c index 262aa76d..9e75e5df 100644 --- a/test/functional/src/test_chart_table01.c +++ b/test/functional/src/test_chart_table01.c @@ -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_set_table(chart); diff --git a/test/functional/src/test_chart_table02.c b/test/functional/src/test_chart_table02.c index 9de73f84..6949e342 100644 --- a/test/functional/src/test_chart_table02.c +++ b/test/functional/src/test_chart_table02.c @@ -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_set_table_grid(chart, LXW_FALSE, LXW_FALSE, LXW_FALSE, LXW_TRUE); diff --git a/test/functional/src/test_chart_table03.c b/test/functional/src/test_chart_table03.c index 85eebed2..28f93415 100644 --- a/test/functional/src/test_chart_table03.c +++ b/test/functional/src/test_chart_table03.c @@ -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_set_table_grid(chart, LXW_FALSE, LXW_FALSE, LXW_FALSE, LXW_TRUE); diff --git a/test/functional/src/test_chart_title01.c b/test/functional/src/test_chart_title01.c index 67ebdf2a..2b3950bf 100644 --- a/test/functional/src/test_chart_title01.c +++ b/test/functional/src/test_chart_title01.c @@ -35,7 +35,7 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5", 0); chart_series_set_name(series, "Foo"); chart_title_off(chart); diff --git a/test/functional/src/test_chart_title02.c b/test/functional/src/test_chart_title02.c index a1bb112b..eee4237f 100644 --- a/test/functional/src/test_chart_title02.c +++ b/test/functional/src/test_chart_title02.c @@ -33,7 +33,7 @@ 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!$A$1:$A$5", 0); chart_title_set_name(chart, "Title!"); diff --git a/test/functional/src/test_chart_title03.c b/test/functional/src/test_chart_title03.c index 01ac29ad..3682429e 100644 --- a/test/functional/src/test_chart_title03.c +++ b/test/functional/src/test_chart_title03.c @@ -33,7 +33,7 @@ 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!$A$1:$A$5", 0); lxw_chart_font font = {.bold = LXW_EXPLICIT_FALSE, .baseline = -1}; diff --git a/test/functional/src/test_chart_up_down_bars01.c b/test/functional/src/test_chart_up_down_bars01.c index b2aad5e9..46bbe385 100644 --- a/test/functional/src/test_chart_up_down_bars01.c +++ b/test/functional/src/test_chart_up_down_bars01.c @@ -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_set_up_down_bars(chart); diff --git a/test/functional/src/test_chart_up_down_bars02.c b/test/functional/src/test_chart_up_down_bars02.c index 6065da54..cf7918b7 100644 --- a/test/functional/src/test_chart_up_down_bars02.c +++ b/test/functional/src/test_chart_up_down_bars02.c @@ -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_line up_line = {.color = LXW_COLOR_YELLOW}; lxw_chart_fill up_fill = {.color = LXW_COLOR_RED}; diff --git a/test/functional/src/test_chartsheet01.c b/test/functional/src/test_chartsheet01.c index 5b5b5c61..c0f4f2cf 100644 --- a/test/functional/src/test_chartsheet01.c +++ b/test/functional/src/test_chartsheet01.c @@ -34,9 +34,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); chartsheet_set_chart(chartsheet, chart); chartsheet_activate(chartsheet); diff --git a/test/functional/src/test_chartsheet02.c b/test/functional/src/test_chartsheet02.c index 3397b7d6..7f150061 100644 --- a/test/functional/src/test_chartsheet02.c +++ b/test/functional/src/test_chartsheet02.c @@ -35,9 +35,9 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet1, 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); chartsheet_set_chart(chartsheet, chart); chartsheet_activate(chartsheet); diff --git a/test/functional/src/test_chartsheet03.c b/test/functional/src/test_chartsheet03.c index d1d42419..f231f4b2 100644 --- a/test/functional/src/test_chartsheet03.c +++ b/test/functional/src/test_chartsheet03.c @@ -34,9 +34,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); chartsheet_set_chart(chartsheet, chart); chartsheet_hide(chartsheet); diff --git a/test/functional/src/test_chartsheet04.c b/test/functional/src/test_chartsheet04.c index 18059197..ff56b85e 100644 --- a/test/functional/src/test_chartsheet04.c +++ b/test/functional/src/test_chartsheet04.c @@ -34,9 +34,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); chartsheet_set_chart(chartsheet, chart); chartsheet_protect(chartsheet, NULL, NULL); diff --git a/test/functional/src/test_chartsheet05.c b/test/functional/src/test_chartsheet05.c index 2733261f..f250b3e9 100644 --- a/test/functional/src/test_chartsheet05.c +++ b/test/functional/src/test_chartsheet05.c @@ -34,9 +34,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); chartsheet_set_chart(chartsheet, chart); chartsheet_set_zoom(chartsheet, 75); diff --git a/test/functional/src/test_chartsheet06.c b/test/functional/src/test_chartsheet06.c index 171a19fa..f2e71704 100644 --- a/test/functional/src/test_chartsheet06.c +++ b/test/functional/src/test_chartsheet06.c @@ -34,9 +34,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); chartsheet_set_chart(chartsheet, chart); chartsheet_set_tab_color(chartsheet, LXW_COLOR_RED); diff --git a/test/functional/src/test_chartsheet07.c b/test/functional/src/test_chartsheet07.c index 38e87bbe..c195c257 100644 --- a/test/functional/src/test_chartsheet07.c +++ b/test/functional/src/test_chartsheet07.c @@ -34,9 +34,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); chartsheet_set_paper(chartsheet, 9); chartsheet_set_portrait(chartsheet); diff --git a/test/functional/src/test_chartsheet08.c b/test/functional/src/test_chartsheet08.c index 3f6cc34c..686d60d3 100644 --- a/test/functional/src/test_chartsheet08.c +++ b/test/functional/src/test_chartsheet08.c @@ -34,9 +34,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); diff --git a/test/functional/src/test_chartsheet09.c b/test/functional/src/test_chartsheet09.c index b7b90f7a..3a1e42b2 100644 --- a/test/functional/src/test_chartsheet09.c +++ b/test/functional/src/test_chartsheet09.c @@ -35,9 +35,9 @@ int main() { for (col = 0; col < 3; col++) worksheet_write_number(worksheet, row, col, data[row][col], NULL); - lxw_chart_series *series1 = 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 *series1 = 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_line border = {.color = LXW_COLOR_YELLOW}; lxw_chart_fill red_fill = {.color = LXW_COLOR_RED}; diff --git a/test/functional/src/test_checkbox01.c b/test/functional/src/test_checkbox01.c new file mode 100644 index 00000000..33ba7d30 --- /dev/null +++ b/test/functional/src/test_checkbox01.c @@ -0,0 +1,25 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test case for checkbox functionality. + * + * 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_checkbox01.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + + 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); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_hyperlink36.c b/test/functional/src/test_hyperlink36.c index f01395a3..ec53dbdd 100644 --- a/test/functional/src/test_hyperlink36.c +++ b/test/functional/src/test_hyperlink36.c @@ -23,7 +23,7 @@ int main() { worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &options); - chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$2"); + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$2", 0); worksheet_insert_chart(worksheet, CELL("E12"), chart); diff --git a/test/functional/src/test_object_position04.c b/test/functional/src/test_object_position04.c index 6efc445f..e591da03 100644 --- a/test/functional/src/test_object_position04.c +++ b/test/functional/src/test_object_position04.c @@ -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_options options = {.object_position = LXW_OBJECT_MOVE_DONT_SIZE}; worksheet_insert_chart_opt(worksheet, CELL("E9"), chart, &options); diff --git a/test/functional/src/test_object_position08.c b/test/functional/src/test_object_position08.c index b86f84f9..69a981a5 100644 --- a/test/functional/src/test_object_position08.c +++ b/test/functional/src/test_object_position08.c @@ -48,9 +48,9 @@ int main() { lxw_row_col_options col_hidden = {.hidden = LXW_TRUE}; worksheet_set_column_opt(worksheet, COLS("F:F"), LXW_DEF_COL_WIDTH, NULL, &col_hidden); - chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6"); - chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6"); - chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6"); + chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6", 0); + chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6", 0); lxw_chart_options chart_options = {.object_position = LXW_OBJECT_MOVE_DONT_SIZE}; worksheet_insert_chart_opt(worksheet, CELL("E9"), chart, &chart_options); diff --git a/test/functional/src/test_object_position09.c b/test/functional/src/test_object_position09.c index abf6cd55..b222c30c 100644 --- a/test/functional/src/test_object_position09.c +++ b/test/functional/src/test_object_position09.c @@ -48,9 +48,9 @@ int main() { lxw_row_col_options col_hidden = {.hidden = LXW_TRUE}; worksheet_set_column_opt(worksheet, COLS("F:F"), 9, NULL, &col_hidden); - chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6"); - chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6"); - chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6"); + chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6", 0); + chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6", 0); lxw_chart_options chart_options = {.object_position = LXW_OBJECT_MOVE_AND_SIZE_AFTER}; worksheet_insert_chart_opt(worksheet, CELL("E9"), chart, &chart_options); diff --git a/test/functional/src/test_quote_name01.c b/test/functional/src/test_quote_name01.c index 5917e97d..9a46baa1 100644 --- a/test/functional/src/test_quote_name01.c +++ b/test/functional/src/test_quote_name01.c @@ -40,7 +40,7 @@ int main() worksheet_write_number(worksheet, row, col, data[row][col], NULL); lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_PIE); - lxw_chart_series *series = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series = chart_add_series(chart, NULL, NULL, 0); chart_series_set_values(series, sheetnames[i], 0, 0, 4, 0); lxw_chart_options options = {.x_offset = 26, .y_offset = 17}; diff --git a/test/functional/src/test_quote_name02.c b/test/functional/src/test_quote_name02.c index 08141b26..390f1a30 100644 --- a/test/functional/src/test_quote_name02.c +++ b/test/functional/src/test_quote_name02.c @@ -40,7 +40,7 @@ int main() worksheet_write_number(worksheet, row, col, data[row][col], NULL); lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_PIE); - lxw_chart_series *series = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series = chart_add_series(chart, NULL, NULL, 0); chart_series_set_values(series, sheetnames[i], 0, 0, 4, 0); lxw_chart_options options = {.x_offset = 26, .y_offset = 17}; diff --git a/test/functional/src/test_quote_name03.c b/test/functional/src/test_quote_name03.c index 9f563944..b87969a4 100644 --- a/test/functional/src/test_quote_name03.c +++ b/test/functional/src/test_quote_name03.c @@ -40,7 +40,7 @@ int main() worksheet_write_number(worksheet, row, col, data[row][col], NULL); lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_PIE); - lxw_chart_series *series = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series = chart_add_series(chart, NULL, NULL, 0); chart_series_set_values(series, sheetnames[i], 0, 0, 4, 0); lxw_chart_options options = {.x_offset = 26, .y_offset = 17}; diff --git a/test/functional/src/test_quote_name04.c b/test/functional/src/test_quote_name04.c index 18da5240..a9c4752f 100644 --- a/test/functional/src/test_quote_name04.c +++ b/test/functional/src/test_quote_name04.c @@ -29,7 +29,7 @@ int main() lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_PIE); - lxw_chart_series *series = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series = chart_add_series(chart, NULL, NULL, 0); chart_series_set_values(series, sheetname, 0, 0, 4, 0); chart_series_set_name_range(series, sheetname, 0, 0); diff --git a/test/functional/src/test_quote_name05.c b/test/functional/src/test_quote_name05.c index 04d7dc5b..9e3c2451 100644 --- a/test/functional/src/test_quote_name05.c +++ b/test/functional/src/test_quote_name05.c @@ -37,9 +37,9 @@ int main() worksheet_set_portrait(worksheet); worksheet->vertical_dpi = 200; - lxw_chart_series *series1 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series1 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL, 0); chart_series_set_values(series1, sheetname, 0, 0, 4, 0); chart_series_set_values(series2, sheetname, 0, 1, 4, 1); diff --git a/test/functional/src/test_quote_name06.c b/test/functional/src/test_quote_name06.c index fe932f6c..b8d29db7 100644 --- a/test/functional/src/test_quote_name06.c +++ b/test/functional/src/test_quote_name06.c @@ -37,9 +37,9 @@ int main() worksheet_set_portrait(worksheet); worksheet->vertical_dpi = 200; - lxw_chart_series *series1 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series1 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL, 0); chart_series_set_values(series1, sheetname, 0, 0, 4, 0); chart_series_set_values(series2, sheetname, 0, 1, 4, 1); diff --git a/test/functional/src/test_quote_name07.c b/test/functional/src/test_quote_name07.c index 08724650..23025c1b 100644 --- a/test/functional/src/test_quote_name07.c +++ b/test/functional/src/test_quote_name07.c @@ -37,9 +37,9 @@ int main() worksheet_set_portrait(worksheet); worksheet->vertical_dpi = 200; - lxw_chart_series *series1 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL); - lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL); + lxw_chart_series *series1 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series2 = chart_add_series(chart, NULL, NULL, 0); + lxw_chart_series *series3 = chart_add_series(chart, NULL, NULL, 0); chart_series_set_values(series1, sheetname, 0, 0, 4, 0); chart_series_set_values(series2, sheetname, 0, 1, 4, 1); diff --git a/test/functional/src/test_set_column05.c b/test/functional/src/test_set_column05.c index 245f0e9f..9cd25e74 100644 --- a/test/functional/src/test_set_column05.c +++ b/test/functional/src/test_set_column05.c @@ -51,9 +51,9 @@ int main() { worksheet_write_blank(worksheet, CELL("F13"), bold_italic); - chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6"); - chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6"); - chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6"); + chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6", 0); + chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_set_column06.c b/test/functional/src/test_set_column06.c index b1a5d0df..c069725d 100644 --- a/test/functional/src/test_set_column06.c +++ b/test/functional/src/test_set_column06.c @@ -47,9 +47,9 @@ int main() { worksheet_set_row_opt(worksheet, 12, LXW_DEF_ROW_HEIGHT, NULL, &options); worksheet_set_column_opt(worksheet, COLS("F:F"), LXW_DEF_COL_WIDTH, NULL, &options); - chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6"); - chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6"); - chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6"); + chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6", 0); + chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_set_column11.c b/test/functional/src/test_set_column11.c index 6e8d0717..6d1ade47 100644 --- a/test/functional/src/test_set_column11.c +++ b/test/functional/src/test_set_column11.c @@ -47,9 +47,9 @@ int main() { worksheet_set_row_pixels_opt(worksheet, 12, LXW_DEF_ROW_HEIGHT_PIXELS, NULL, &options); worksheet_set_column_pixels_opt(worksheet, COLS("F:F"), LXW_DEF_COL_WIDTH_PIXELS, NULL, &options); - chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6"); - chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6"); - chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6"); + chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6", 0); + chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6", 0); + chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6", 0); worksheet_insert_chart(worksheet, CELL("E9"), chart); diff --git a/test/functional/src/test_sparkline01.c b/test/functional/src/test_sparkline01.c new file mode 100644 index 00000000..03fc1c49 --- /dev/null +++ b/test/functional/src/test_sparkline01.c @@ -0,0 +1,33 @@ +/***************************************************************************** + * 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_sparkline01.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + + /* Write data for the sparkline. */ + worksheet_write_number(worksheet, 0, 0, -2, NULL); + worksheet_write_number(worksheet, 0, 1, 2, NULL); + worksheet_write_number(worksheet, 0, 2, 3, NULL); + worksheet_write_number(worksheet, 0, 3, -1, NULL); + worksheet_write_number(worksheet, 0, 4, 0, NULL); + + /* Add a line sparkline. */ + lxw_sparkline_options options = { + .range = "Sheet1!A1:E1", + }; + + worksheet_add_sparkline(worksheet, 0, 5, &options); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_sparkline02.c b/test/functional/src/test_sparkline02.c new file mode 100644 index 00000000..b55bffa8 --- /dev/null +++ b/test/functional/src/test_sparkline02.c @@ -0,0 +1,36 @@ +/***************************************************************************** + * 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_sparkline02.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + + /* Write data for the sparkline. */ + worksheet_write_number(worksheet, 0, 0, -2, NULL); + worksheet_write_number(worksheet, 0, 1, 2, NULL); + worksheet_write_number(worksheet, 0, 2, 3, NULL); + worksheet_write_number(worksheet, 0, 3, -1, NULL); + worksheet_write_number(worksheet, 0, 4, 0, NULL); + + /* Add a column sparkline with high/low markers. */ + lxw_sparkline_options options = { + .range = "Sheet1!A1:E1", + .type = LXW_SPARKLINE_COLUMN, + .high_point = LXW_TRUE, + .low_point = LXW_TRUE, + }; + + worksheet_add_sparkline(worksheet, 0, 5, &options); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_sparkline03.c b/test/functional/src/test_sparkline03.c new file mode 100644 index 00000000..c2162c23 --- /dev/null +++ b/test/functional/src/test_sparkline03.c @@ -0,0 +1,35 @@ +/***************************************************************************** + * 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_sparkline03.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + + /* Write data for the sparkline. */ + worksheet_write_number(worksheet, 0, 0, -2, NULL); + worksheet_write_number(worksheet, 0, 1, 2, NULL); + worksheet_write_number(worksheet, 0, 2, 3, NULL); + worksheet_write_number(worksheet, 0, 3, -1, NULL); + worksheet_write_number(worksheet, 0, 4, 0, NULL); + + /* Add a win/loss sparkline with markers. */ + lxw_sparkline_options options = { + .range = "Sheet1!A1:E1", + .type = LXW_SPARKLINE_WIN_LOSS, + .negative_points = LXW_TRUE, + }; + + worksheet_add_sparkline(worksheet, 0, 5, &options); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_textbox01.c b/test/functional/src/test_textbox01.c new file mode 100644 index 00000000..0cc43770 --- /dev/null +++ b/test/functional/src/test_textbox01.c @@ -0,0 +1,21 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test case for textbox functionality. + * + * 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_textbox01.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + + worksheet_insert_textbox(worksheet, 8, 4, "This is some text"); + + return workbook_close(workbook); +} diff --git a/test/functional/test_autofit.py b/test/functional/test_autofit.py new file mode 100644 index 00000000..a3f0274e --- /dev/null +++ b/test/functional/test_autofit.py @@ -0,0 +1,19 @@ +############################################################################### +# +# Tests for libxlsxwriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright 2014-2025, John McNamara, jmcnamara@cpan.org. +# + +import base_test_class + +class TestCompareXLSXFiles(base_test_class.XLSXBaseTest): + """ + Test file created with libxlsxwriter against a file created by Excel. + + """ + + def test_autofit01(self): + self.run_exe_test('test_autofit01') + diff --git a/test/functional/test_chart_area.py b/test/functional/test_chart_area.py index 0cf33941..691aeffe 100644 --- a/test/functional/test_chart_area.py +++ b/test/functional/test_chart_area.py @@ -23,6 +23,11 @@ class TestCompareXLSXFiles(base_test_class.XLSXBaseTest): def test_chart_area03(self): self.run_exe_test('test_chart_area03') + def test_chart_area04(self): + self.ignore_elements = {'xl/workbook.xml': ['', '', '', '', '', '', '', '', + '', '', + 'gr5Gubi{LefHkp)ldaqq6Xjt2mt^9J7CRoD9#iI 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 UNZthiXh@&Cq+ETD?fb9)0fJk*`~Uy| literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/autofit03.xlsx b/test/functional/xlsx_files/autofit03.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..3e1fef885deecee22637e97e3f9f927f22c9e604 GIT binary patch literal 7388 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/autofit04.xlsx b/test/functional/xlsx_files/autofit04.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..cf58bc3391bc5dc8a00ada92b19227b2aa0d15d9 GIT binary patch literal 7449 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%0D!-xz+d5iJ-_}8FQxbs a{6D9ex-u4;8vpw2M+I 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 F{tt}#LF)hj literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/autofit07.xlsx b/test/functional/xlsx_files/autofit07.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2e76bf09f7259afc7e9623882ab03d3948a501fc GIT binary patch literal 7876 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 G0Pr7`mya<3 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/autofit08.xlsx b/test/functional/xlsx_files/autofit08.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a425503e78264534367be78d5c9a489aa896bf89 GIT binary patch literal 7410 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 PT;wMJnW^7U{rL4i^gZY| literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/autofit10.xlsx b/test/functional/xlsx_files/autofit10.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..07433749b7f5ee1665cd3224e721dab2edf37841 GIT binary patch literal 7520 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 L&eWf%e|-B7UR3vE literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/autofit11.xlsx b/test/functional/xlsx_files/autofit11.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ad11695029661a69495ab930a0a3539969d69c6e GIT binary patch literal 7345 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/autofit12.xlsx b/test/functional/xlsx_files/autofit12.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b133fb38a0a740c719de78cfada040570e4fca41 GIT binary patch literal 7466 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 Dj6U{& literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/autofit14.xlsx b/test/functional/xlsx_files/autofit14.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..db5552144564678ab34ddbdb9e7d5ce630926efb GIT binary patch literal 5858 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 F{{zJbol*b* literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_area04.xlsx b/test/functional/xlsx_files/chart_area04.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..25222cfbb8ac8745bf7370fb328337769b850a2d GIT binary patch literal 9274 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_bar24.xlsx b/test/functional/xlsx_files/chart_bar24.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..26e690afa509e1678349a7106f1c3bd505bb57cf GIT binary patch literal 9306 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_combined01.xlsx b/test/functional/xlsx_files/chart_combined01.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..778f55241067ddd835af067393bb62dbecd3a34f GIT binary patch literal 9198 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_combined03.xlsx b/test/functional/xlsx_files/chart_combined03.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5c5b2f1f18c5eb406280e32729f3166e35103825 GIT binary patch literal 7801 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 NkOSX=UF6qK{|7aUvS$DQ literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_combined04.xlsx b/test/functional/xlsx_files/chart_combined04.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c4ff0eaeca3e3526040cc94dc4aa3c060ea2b1d5 GIT binary patch literal 7812 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 XSC&VHv-n4zj|H%V8v-uXkGKB;NjV*D literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_combined08.xlsx b/test/functional/xlsx_files/chart_combined08.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e13215f4b30a7548e2ccaf9478fdbbbc6e6857b3 GIT binary patch literal 9437 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 rlfXLsyXC@N@xMpkS^(vmZ4z)hZd0T?yfVs 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 Fe*lHwN~Zt- literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_combined10.xlsx b/test/functional/xlsx_files/chart_combined10.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c2b16cce7b95e7a2ddeb7071358662e8138b4eaa GIT binary patch literal 9450 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_combined11.xlsx b/test/functional/xlsx_files/chart_combined11.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..7fb6ad7f756165be75c2c65270cbc56f02cbe5a3 GIT binary patch literal 9491 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_date03.xlsx b/test/functional/xlsx_files/chart_date03.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..be97dc397df812e9c96cb6d1a2937ba8d6b4a60c GIT binary patch literal 9458 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_date04.xlsx b/test/functional/xlsx_files/chart_date04.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..456cb7894076d2fcbd1c9cbb84f67e99d91227f6 GIT binary patch literal 9462 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 pfPdr+cg6qi>HjKTNd6b`KmER%A`* literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gap04.xlsx b/test/functional/xlsx_files/chart_gap04.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..cf57e4a8f653b094c53e26e03a591d26e9aac62a GIT binary patch literal 9316 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gap05.xlsx b/test/functional/xlsx_files/chart_gap05.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..7f6625cea605a128a53e61bce678e2d677af4fec GIT binary patch literal 9312 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 {H*jU6E4Zurb(`vb+40{FJjNX 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 VGzx;nKgxX^fC<772q}L&{SWJwE2#hg literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gradient02.xlsx b/test/functional/xlsx_files/chart_gradient02.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ee250129ba0cdcdae56c3331a98caebc0aec8da2 GIT binary patch literal 9383 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gradient03.xlsx b/test/functional/xlsx_files/chart_gradient03.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e3710411c8c4cf696465f44e73708919fa8900e9 GIT binary patch literal 9384 zcmeHN^;?wdx*kAULL?OF9FP)_2I(A1LP9_qB!*5wx|J(_DQtel0XTxozhT%k&0B!pb zD8E()B1&zfzws*L4p-~0Zrt74o8qye#SK@@PT*0mnn%ytf)xiC??i_KCqm zjm_BV!e|fX`9srqeSCHFWv19|K#$4jWkc`50s==twMIFg7U|O`dCtmUg2WF_L~-?hSS_5Fxw2L8XsHM z$!TsJ*eMH4pKtI~bYl6`@zW*BC{~2Qoiynd-+1;)^=|-`Y%Wu}wXzAGvAn685RkBu^ zUGl2%Od8?S6F(#$SwrZ^$@NsfzRHo+m z-NX?j`Y&eZEcINnVv`LfF7wJmLy7BSuc!?;Nfq%iVcT}uQEbY6`eq|B5A%#?VpjzN zTF8``1;!w+(NNt{3xqBN&dX~!<-snjYaRv(3Sq*j_xbysR>e#(^M{~$NuvESz66IU zqxX6*sSJ@)>84*Q9^F*)*iy*_4@)l`3e1Pt3vX?CvwSqmKWiEkSjzQVls7ulhjiko z>cQ3aPp*dtPTMTNSD4{kCkCJ)xLC6OL3d}corM7yZ1E%1{7L;gKd286O8>vFPf`7^ z;htII)c?D0qKBXpMs{q^RIF%q=QV)x9eGE*pGoxiTfIe}Sz&3eDYRmgS$i5Q=V!}l z3ix%W3Sv>KX+4^Hr^RFYY90bjJ_b*UxqO|o^r-@L&d*A(vmnxZ9XjM1*@WH1d{O%W zJ=K{bHfuq|i#W_MZ(1!lG0C)h|eFbwe$%I|WIbJp^o|XbQW_J9!id z9|~Nq91#7EA4f0LQKaBHCxG(<2d;QHKmN*$Fy()TsrbFGGSZA%PxJi%BbcHY?<#_S z#Hk3&z{Yn9-lX@FYQi+gAZR~7Ka6- z=(dhH+PYVK3m5btwx>c%(^0V4gVGune@b7pHqjd9$q%!t?fydc-h$a?@ikx`7%x7O z^7Q3vJ}Rc2w`?G_Uc6M$)YG(UGy@UacSkzR+ESrvv;^By5`Hy1kHC?qn#viqheM)n zxV-XZoPt;8lf@p}Ss0^CeZa@XRP)UDlwbobFJ9yQyfQkf5royF|>W# z1_JCGViPCBgOHwa2|li4R8~N1H;6WY8B8X!XuU!D-I=e>YQH)&(_z&IP=^J*(gT|N8o|+w-p+nUYwwOS;pA&_<>_=74@1n9w4(}F@ zp`qHhVO!rP0ZVn2u+I&C9W!`xf9O?DT@UMvb8?A<{`o>(y(lO9jlu&}aOiN2>|>qh8C(?gTdU&Um4oM0^X1!_~(o*2N!@?Wc_}k-c*>?Us%Cj+yBd9Pi#+UfoOo>_tgO5s;dJ!Z3kV65W5qlvl2# zx7x@3+szY{6bLlIS04Y`{0|>uZ)R-lVE<>h`T6jZ)&FVpy5jqc#|ZI8m%dhb<*-~Z zn8n9u!OAq@+9YTCS+4R7!@73GWlZLs^?F@|GAO8v2~6RM za|CW*ecXXMu{rFoaYe~JV~Pzw>lt9jGnA6?jol+{34FfRllD#4L+#V=BkX1lZLJRq z0HE^dM=AHygF2WQTN$(d{QSA)ZB0cmlncKFXVRI%0c=HI{Rq`DWU?%|Nd8fWbs(Af z`*;nN4B;;_9*?G%y%5^#^%D>pcGxT*4e5BJ3EJC^{c(HPx^pIt!Hb1Bk$)8m(W zI-SXkH1|YGh2oQIcl>2(ljA~;^dI#13s64!EMFT`>ht2BY8N6o!fcS*c)^$nZ5!u_ zQW!ObyE}WjkcgQ47ieG5>4U~D*>4CRgT3kGQwUJ_Q^z?)2aOZZ9fCBWNJ565oHRJG zfe+#_=%#hYt{VHs$1vtVL{F*=tn_u}uf8~L`oJ6p_VFP=Q?0ED?H5jV7bvY?*^4K( z9Nnu@QW0LwqskXCNhBSAmn@1IVe;BuX5X={QZ8yZL%cqweXspNA$LU9xJ(?YM`%1@ z|IwIOxKwouaas;ZaHSMm`=vODqwRJ_Z8-Fy70=GO^~D z#9taCkC5e6p_gos$a|P>C8=+3zMZQaeLIg?4jhUg|L$BRXJ$5CWQp)yYD<{+ zJXxP0&wQ5Zd3XRLT6NLvxVdPjZ@Id1<;7(;qZ|ok{dje<-5XjWbbZ~>O}lU9EhTXl zDJhAMpr|qVRu!NCZZY#rfm1g zY$T7tE(ghDlE_40*7{j&B;L-h^0!IHcNac#LdqLt5~LtGdG;)7`bff1C-Xa=?-Mrf z7CTv1I1@SYJRWrmB&nB{M*A%5M~=6a2;)m-Ac>12SqdV+^1NSI3hIHpJd=2-$hhwy z{6MPdNmRMzfEB_8VTvb`SQDe;C0Vi*%X1(fbEfNkdtLF}eRJ*(<>vvU!#qp|&mvXO zl*3Ny7=8C_xy6q7&k(vF&w3=_b?N&bN9pAznYuh4eBJtt5VaDRL*v(7S<7E5{Hg*4y;vxNk;IS3 zo2+5YoXQ&{gNjG{vTbVcZo-#wmyOXl!G~N&?;+zz!DD3P&_zeV6jCfZc9VYe&*vP5 zmBr{OaZ?v@vB11*zR$0<@;K}ZAC7?X?Q2&VeQ^@hd?7PQ!~PT-I<0;3JQ)__He8Uf zu&UV|l$5$omqjWa8ZiO7{CAae{Xzu~>5a<_Sdb{3WZz^Bx#nsVwH9UfHY3zj@Z|Rt zH~Z+UHF3k96GAXqHyZ_`BA8g{=tD=8p%zcaiOCLZznsw7eDd!GB9zF@p6L^|&PJB_ zVO^@kOc|ZGB^QC7aHGGrQPJON&MH+w#iJaNFu7e*`d`gqEO}dJmp@t^ED4c0$9$gs zpzDT1?Z^{x0(r}D2Z7w$4q1{<4@ySFxT54A9eLq_5bm2#ipy+6iaCm_YV*YBCHQmREQ(pF$kH*TjYTeRHszjsv(lu0J|#bTTBtG^MuV zRv`d&4-MG}mPl3`Do0EtsP<7$Iw@gjV)CQ5i30BNL@UHF2!`KEjbxc{YeCt#|q{Nuq$)N)5@tm!g*62JAH7j^a#sur`7xpjdx|EPDr6OJn;VS!b3C zfu7mUR{WpQ5LLxcf!<&e{NOoLa?{bU8tH*5{9}2X~yENo}Nce0ivax zC1?F^;tLGHw_C#a0!YgaL`q0v$5CZ~W(7lpxdXrN)!ftT>I(~}si`0a*YP@Z@<`V5 zR!#7n(X~aD=4Fd7^YF~!}J`CnHB=6C~WO1H~qGpxEz1w z=m%eMzyJX7|IntPnZ6x7_4;}HnSoTQ%e{m0+-+tpy@6O9P0OTAfWl=$I!5u4bIi&{ zclE&`pLwSHqA7bvKey;Tk3KY8hU@|cAZ5Mp@Xv#(950>p`d99S5oisJZof{XORHt^ zFId~0VBMPFHa8$up^edk2zVeSH|tz|hcXYHM?5?oX2VA3Q|4MfbXb2GgM$*kmu7Mz z%bliFGnQk5{Y?HT5bH8x(1P~?R$zsrNBrf<^ zJS0(-tiduN?<}vvz8foI4v9<$o{9+GHL#Km^33Sq`gpJRps&=9IqPWeWNxV*SSgda zBS30E%v6&zjnAGmKii~DU~#}lF~i`--Z4K!2o4z=*q)UL4P#yuG@=Fi8(ZlzGR90Dh$VSo+ z%_Tj&l<$OH0+!Jdj}YkYEpP~Qd8LzZV3DUj!ib%0yU|d57OzHVC%{k$bPZS~C~Lgv zWIBzWESu?9?mqbRt|MYKSxC6sj!QtQF=cH;kyEOdgOfJ9Z`4q!5_;k4n@?6=mTfuwkd|5SipZx|d(9hZ%aYm+Va%z|H$*#O zqKrYs8e2#6uQCWc{Ari;;~v$;#$mAUf@~tbC_;<;CkIQVx@~ZR4UcsU79MoS7_jP7 zVAm&IXAZbi%NpJP1TL5?9B%%=sXw&+J-s)eJ@Ef8Ew?-J&#Ikrapb} z&cuoPUR4QfOdA?WZAKjnGONV^BD^mY?O{xRdo%OBF{?v^1#=FFj_!dfR`P}1)VAa( zG#`OU#FrDjsAz|(3#2R7KOpN!VVkX5ze<=}Z;&(Eis_tZHOYrIsM+tIHHW)-W1Clw z&pVTMRfTNcBrev@yas+f@-V5(zqKlzA|oBN;rL+3IX1g2^ol8s`z9=SHE@1d*gCxx zGtCINo%XfA6h@}ZMq)faI9K0B_LL!Qr6k89oPo$ zqQQ2?e@y%S+kJ(f9N$6IEDuFbKDoiYQAN z;t=gAiF4~@m^ddz_JgRk(Q!dxjJr>P!*lvcN>|Irui`E%(qGUisGT>V^JCfOS~6fS zZOqlZ=B&0#uGA!_UdcVPIzO8!A%0Qc5C>3Qd(Nisec2U{GoZfi@_ZxWh5dTM;@}p> z%8uuL$~aQ)I}b1KFi~8mAP-gDiiXQE#5jg@O^{4V&SSTB6TgA-Q|s-L?<|w)X#tBj z_gM|19Xn##?K;i)D9I3vBNTP}ey`WR`24!YwI$pm70|pw`I133Qtn$X~Py%0??rT>!AdUwiMEe@%JH3`j5rf1u zN%e|WE2A<;$PbO*ZntdPAJL!9pLZt-hT=H zxO>1&;xE(R+k$@|p8ZwO9NzHz&!e>4IJbu^zmS6AuY=qgx!e}MJuUbpe2xB7__woz z+bFji)W1-MG5?P8AKKNo0dF^be*q5M{r8^!w-)eiz}tP)Ux58^w+26?+g;V$0Jp2! zUjUx)vIq|FtH!-8db@=BB?=<^Df*9s>NdjdbnX`dBJu6x_?6tb9knSo}84lGl%h%d3m9`_R3c_7! z7EcVKwa^t2R;eTR0A2c{H}&1eOF+i_Dy1@Zq5GCMJy=*CJ|~*n;_G}wglesU&IFU% zFt?UWPAenR@GKjp?V6+AWXz})o+bo*x2VYAqsHa1p;YJ3NG&?k4OAwz;-n3%DuE(N zCxr^`O4jccR6MP$Mp55~HRGzFyM>{yf&fpl`S5tizXG*&0-v0=-6BR!#l|-7cY6$+ z0$__H?3l_^dx-Ij_e=fK7VF)l?P$L?C8;jXL`@{6Kb=Xw{)P&rEJqreqvL=mkIE6q z5<&tzx0JJb4su+JEC;Qm;Z#FKIeU7eGAC}@@?Mn6t#!sE7#)sEh))i12x2<2`<{GP z_hWR^z%w|^Lb7PQ%DFQvxVKEqai2Ve0|4&tp#d^~Grmd%dZIH3qa+}zB#(!!O()e_N6uTysO>!Y(V;L!5hYcd(7*`26YDd!*8BMd z6Ag#V$OP@lo7}RXAgsE`TOw^H9BFhU@Sasx7`<$dmf>*3%Ur#=$aOB?CR`aB&T-I3 zcsOUceC}(`tFme)NplCf4Oi_LsbHSuXB@qD>-_pid4sdL@qE3aUKl5dqffhU2z8*7 zNoPJtpWauoSrUo|42dkAa4rT~^X%?=(54vXT{aGIuH<+xOX^-~f!a~zH6UvHC)Y## zW-OKM+UV*%iS4kmPe(B0nL%2?an-1tYR`IGvOeo!A0l>UETU&DGoLOiqJh0k}d zSXVAP#H`4!=}5k+_B#N<7reG;Z~gEIca3Gwc^(m#Y4{@8d23=*`?ss9Qs}i8Qv6}- zsa?t%7e(Vo3a*@up4zXASiI~rwFrIHt}aXNGC?BjZEAQ*Szfs|zn;cBdryxGwH(O+C%(6HCLiDEg6Hl~} z2&PO_08M~zQzD6QbMIw87dSlGNAVilQa#A{Njn$LH&;#zVd8?$vUWD<=Px;L){ZfM z$B)zZim<{Eont`wfdWxHgdcxpMzHL^!&LO)n5YP)3Ui(}U>J!n{Y!bkk2v+&#IM4A zkX;sWj%|N*HEw$RdXD@UW8f%bHj3-7&#I|%z5*#!*fdGvw_Xa+@!yylql^kGQ9~nCp z;t&0ng^Q||QdSDSRXbcCtUVP=tKtIvyE9*3L@`Q&ocS(f^~E1&u4|=bZ)9d*P50-Q z*FVfMQ4aLOeKkUI1lfZjGyK^6O8D0vH2}Cv0F~sVh~&FBT2$^|BC_@HLx*U??y%p^ z(hXee58=#;+VsSS(+yY;WInA@)K@*Op1di?Fc|R4ODh+OzU60klS@ke>W3B7IEzmN zwTfsZzTmWosk|XT#av@OE6zXMkq#?OYgUe>B|TQx8|~;8Rf|h9Runa2-T^P|V(};e zR?h*0ykEfaH_gmS7{Qr?5siO~z^^$zn7khL+V;irIP+Pj9CcfI~ zBRuVqQ@o)v&M{B|pTDYu6E*NnQUY<%?cL3h-e{{$V2u~gXwdD{ExGAs&NvxFVgGcq zPXtaE8z3tr5VaCLQ0X83_OFWl>2JNi^dq*=qk12D9-^L`jX0r(WjFc{6^y|tjqIaT ziFOHmv;tsUaa- zjm0;=fgj(VvvzMXX`7K&&iEzHfACJjrAVZ-)9C?0~@ zY!gE{=yqbI+eUoR+@ZZO6P*Zh(WP?0ehiLxyXjN8m))PPgD9jF`8lW21Q`AHZd3MW z?dWZeHdw;M-%>}0Tz2&{py>#UdPN@MH2J;T=t|uYb5;2I`v|+8O;Y0t3joNy`ccaL z^q@9|dZv1GKR9tDk_aby_jN`h9v6sv)R)n-o%2ze4D1jB^pOvKPJLBe1U~#{C2c-Cgb%SBY%T zX1x5<_z8*EEoTeVik$r0xba5W44v(L@5Eo>h9h?B^f^e(EF_8?&P?1KsU%q@YuM&7hN8(`Tj$EeWT56E zoMa)jVEoy4p~8q^>Q8&C4Etu4vW4}RP6oFJv^zI3E%cdq14cdjB<{RThdeYd&Y8V0xG(a;zy(|-0^X^B~MJKvnd%XpjY zc5)2HTz61zyT5KFYr4I4e1pnhNH82kmvVc)*Bw;MeRo&iNpfWBAuMM8T~x;Wn2*@g(4 zue8{3n!34s1bQRvX%iZ8(}PN*(nmHxn;L-1#u+AB^fe_$U>h7*%>`@i;LNQTx4fbZjWip zMm6f>hg~Nk0^cX*jfb`o3uaHIz>W&TUh&63c6(M(BGCo##DD zepBG}^F%jj{zgjM8{7n8+IQsaG#QT1tkne$j*M8_WZ(JX46#vbzYUdxmkmCzrSv+q zWaU5QxCC}m&AY~+brPmV*_7bhQ+x(hM9wQrA=&Fx@;UBFnaszz3o zQx@AxCI=N*+=E)`y$rzI9!eSu4h!S+_O_GGySoSZAGnPx)zFo48|xfPTuZmZGomDq zy%|_!tcA?PM#;pds5@L=jP3RT!`A$=iM=~3YB*|mG|OQTin!A$vAx+maO*dW2t6c3 z;m}Avv`h~?jv1M7*cy%EddYGc2bzEm7{|q%UAE;)#6h-V(CmTo*@!2${nuAJY8O{{Hq zSSC~>=I12M`%79%q4TsF-NJexiG8y8?d^ZEw8KSo2S}FBP;mb za}W~Ub^}+~XKGqfvY=tvS!3o2EZk$uk#kauuRfjRz+&tejbCN}z5^+bSm|(?!@tv8X z`E!wRw=SQHf{mS)!0f=c?5xN^^rv1HF5W^Wq)+H;H2f&H7_-sL$Rq@Z=q#eL3r(}< zRuW0oz)-zQdu;lm{-ag}a!kFtNUV;Dy_yS%D;{Q9Wv|u;iUUQjkltmz=(uN8ICX=X zgxS^E2jZDo!3eQy%;I8FuF3d>hhDn^L%i~EP-!f1kVaAEEmBOrBU$C%&nA{LNvO2u zN#hIw5D;&|5Mc;zWTGWbllZ10sDVIiX#{TjZOOgtGUJUUpLs67 z8=w*cR1GWnxCJ)-I^2{qls44P;!#KhP6a4aRCzSJFrrGON?F4qC*g!k%YUJ;;E> zBkc@3mh;nEHFp0p~JxE#G?J%ksKBIK9b~AR2`)RBG|=T(n3sFfs3a}TXr8RUwgTScO*E09 z)ugDtctt_Y0%F?}yV@+dzg7zrzzXsGR27*ad0bj|^Ntt`^bMzw1cVkV=19EbP8k)S zamGIHw?LRuLEt3W5RxS3S}~KExW>EBk^r|}$*+uI$|IJJ0F73!U>ZHN$|DC;WYxJtQ$Cmf_G!$a`f#(){#E z0hX0yR&9`9>E?0Qe5_t}jdXf_Zs-2Ntb%7eqM{&9`tpH>hHG{{l!>?rQ{6%Adqghx zT^@8!=v5m`8EF2quu{M`DIMU#vG?~X)|pMkrKOAHWC;q#iCP4_P`a{aW%C8yJL5{_ zndjDdoP2%O36efBh0>+;WjT}ZKg_W?3)`Y81@Y# zNci8?oi^c7bYGRWx2t)a5kz%=LB9$^JKNYVitdJfK~>Q+x>uG$np#8aoqv3~dw0A- zD*06>U-KPR*QjvG_UyI>-NF&VBK@i&@@i=6Gd(g+Y1RSe2=&2ZYkz$&758lb2KV`6|yhnx=Nk(6P;!7bj9b__uu0ee$y8)$o)} zV7F*?{+dTOCyXuFHtJkt%PUKes50TDCh#h^dSG|5kJ=v{ZS`6)cFEKDCAPef`Kvze z!1W1sdYMOAF#NvhQ!ut~{VOT(uLIC#U4)1ey83V1>#Ds04MQ25 zPIySiiHU>m%0(cExz7~sx?7I+am-RR^=pvx9ZZdQ$%|pjmGfRy`Z(DxDUl;36Q7{x z4cuRKoWj`pqNJe`Ts+%Jug9ytLy;8rY=4AaDvK%BFD^s)9t?k=0Ix#7XNhvs-#7## zvFHWWn(2p=xs`8;)Tlr^W{bWvQ}ak1=c7lxG$Vua5drfzFBQOeD3cd$Gd`5B+9$0? zA8dg|gv|yH{y=DUT`X=+R&?@GpL?Cr?=$tvUEo~%j5UPl&9>uPl=3-I?OrP~VVd4m zS~S&Y^Ev=cukt-Q*d-pWX&9SCdZ+qL>*|a`*v7ZT(a30kUA%Vl zYI?uV4lmF`sdL(bvtfX+Fz0x9X{TdR?|aqa;%#E>^ykle6xU1bR-~5jr~<38w=TB0y*mcyTEM?)kPntIgBj3jU6$F5 zK&E$*rmpOW@iR!(!f?^eM(ZJEqqvEgbX&MVkb0{eJ+dZvrH=l5@^We`bk%`-m&`<} zXPIuG=p8jyyN!D77j(I4mP^6Yr0fa(eT~e~l;8SonB_Fv8i?QShFJTbjf1}wTE9xH z;D|x#OnUTBhom=enHmq#H~i`z(KB>xf!b>77dVbS2^os2!rdLZRy?8Z(K6qkJa;~< zEC!FO&V~{h5=BZF)*zAt;|ln?DAU~U=e{>&wkgpfEs!H1xWe%lkKh?t7M}*?0jYVt zm=FpJ_X#^B)cJe+#cc5{v*hd6pXbzRXOA``+2@*0vBM82_xfZmpl;t==9ZzqnajPc zgfVIq;BTebF#kCGGQPv7xiSquJxyZE_Qk$^WL9a=Ep;mEeQ?0K-{KIDSz0qvsxJ9n z>R4|H7+01aTW@h-p{@m&nId(qIK=hc9gcr~6?t6xyhZP*QbDq&EjcR=-T`GWORNER z^De4zCsXkB)7G^VrV|^k9A{}(B0WRgvt7Zvne8Tj2I=aIuB@_)QAW%}1Nq5z$DOE_yh#lfpE|?kp+A#>6dI~};u9NRcCY^Hk z+2C>$O(*i8$vX@hvR%JK82!3_R8GxDgnA(1s5N}%{a8L!-!%w0Ke$*bwLpF z`bGLC0wU|U z?7nRgWCW$5^$JoT!m~`!VpD=E?ww8q(M3qdIywPSY`{R(JFwTxMl5~=H1!mrCW%UV zMKqczQW6NJ*CUE_V*oYh3SVcG4e4U|n;oi1QO|L?HxX}c+BZ>iUu~-o7pG0xwiVEL z+=tQu9+h?C-5kdL8hK3|2}B*ffqoe<#cLnrC90us;&GB}^42&NIE*<>rj%Gah{zo& za)s$zhpIaC#`1G)QKGeJhwe5?3kATv_>bA5wj}LHQFV|_wm|?8JqudShKazFNy}GlRmjP$Bo90?d-%n0k z&#WrRuYx(=PDVD|>fQZ&zzc+;fn>kGf4|~i+WOc1H*Z_Wi2ohn?=#|m3I4ddLQLW> z6XS=1e;>I0RnQ31B>d0gw}&_n2Q$Br0wAxDJQ&kF6n;2i_$7RY@KgA=^M;2g51ZP* zP==8Hj`AN`+z$aCHi~}%_CNmjp8mJC@k79ez1LrWy^y*Va!3z5u@3Hpk+#sbC z1mIU){802^+4W0Q;`vX}e-vR45gw*t%@Z;%!0Ca(ElmGw# literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gradient05.xlsx b/test/functional/xlsx_files/chart_gradient05.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ccf72ccef0cdf3b01c90608505572eaebda3cfd0 GIT binary patch literal 9434 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gradient06.xlsx b/test/functional/xlsx_files/chart_gradient06.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2447dc5c643f7a3ca1d796aeec8c10eb31670526 GIT binary patch literal 9431 zcmeHN^;?wdx*kAUU_cN>x*G%pq&tTW3F+?cl5VA2x{>Z?q`SLQkWNWCqigN$S}gbZ z1J2ps5A)4;z4P4Hyzg^A{mDwgJi-LP0T2KH01*I51pn9)3IMo$1OPk%EJ3LYT3Ol~ zSlVkTx>y_7Y0x`cm=k8sK~bgypdr8i@AZG~1U@PDOSdxun@En)B1ssf=! zw=>+|m9vE_b=Nc<>>kdtTaW?66?5X*m8+OJD=QNRF2Z|jfU=zG6*ez*pR4S|)D%T| z&@G=D#pz%wBd*iN>;ZZV$8Q>YPgbCq3u{y=I7IG0zwX1q@%BH}-jUoCAR*Rh4{;-! z)`h*bVR2m>n?+#VD(}=D@1=MJtnx7@61WAT93M5WMvkPry+{76H`_#GUN1@B#HJP^ z_VKh>$xFrVjgp#=t?fAQO=KIs8m4C?a2*Ul%@rWvqx=M=s~3WL)^UpzJCl&myx;3R zbOwMcjdoU9ecT2+BOB2Uj5NfF2y z!WvEnbz!4m`xNZ55mO0X%fPFJj&<|#1HMZ6;=uo{Tw$X-KH21O93(kC#3_vJ!Vz%# zT{Do`Q;WdpFbCPX`6}}KRl^99RA&de+YzrAM1f^wb zU~b1i|KpP|v+ut~_kYIN!lH&DM)tVtP^?LC|UiGDeEfYloTwMm~_6AD+a%Nq(X;bIoG-b4OU1B2>%x;|bxH@kZ zm&~=CvtyEVr*HBrLPK#HVs1%vS@2{qk&pLmb0Qh#`gDv(qo3y+EW~Vb2ejhL(s50K zO%dST;0t-KxvnZ|S){C-8MZuh|6Ql{vewVYeZc3?30%IptaovE$p_^`=iVF1TzS;#$k|Tb0tk)B$&*DQZE~_D`;d z2hLfqKvw7=T*m<*KslQ;{6TjoD_b*ND=V`fq2^EOKl(v^NKpF!eSM1TH-&g+;cx!m zeG@#m9g%WkdS+t;YC7)#L>~w`;`|Jwro6OPeHQt|SZ5JR;1=yjEu47Q)1@)%zex*5 zZl?FBYJDr2JW}%DYWC56S;Fe;l&wP?pmB9sc9#tn_mSMf$oaAA5ly^xCZWZ!a`r8&pR>I2E^`geSB zCSusKvB7k~0j()yqHX<`gWShass75>xHg)hW~iOqcr6}W)}o|E-4&heGEbj#-E5p- z|BfGLZFMjdS2 zD!+zvd*Ij+Bcy9cn;p)R>6LuSShX}%8(}X9v#9GH!%sA$vtBg?EK|k_ji$VMYsx`P zyYIyaQtHJ>125($Sd3 z%^)TBG`TUfEMLqPk$jh`x(iKye6zH1VU82+))jb|<76TX?))2s+%D$=AR8sXt}!NI zCOim+mzA5Qo?1>CpyfnLoW=67elxr}D=5pw3ckkw~@oVmWOj+2R{ksZUI zUtaz&%M=Ch5BJp!$r0oZMl1;v3ab%bde;HqF99@C(_&KcuXSj=K1Aml5Jrs9N8aJ` z&NB>M8;;=3i`(}lMKKK74P~R(C>yGu)K1@2Vi^tj7GzY4#N7&Vcq)8M{S=53+B{E4 z0=M=Zn$jCv_Bm%tMXH?54 zxK^TFrA$jh6O+0xpA2jF)b}vFxgrpb?_Vy`)QWVp+b%j$vnYBRTt7zihBN@+e`ma$Q#K(Lxk zO1ZI;_>BK$Mx?2P#C~97@4`Fyi}zoHVu3oSIGUKF68&WF4J97k&p9M%BG#9$X-KYj z`-{$c=ap`$O>z#EAr!9b;l&QMNP&=sJ>_qX4945-L+X6_#zSvsZYeD;^Cl@E3j3#< zMHM<*Zi1|kLDWj}K&5~9+rKLIr@!_4Fo^V-5$Jd5a|pb!9CHOm<~9e76ivXZjP0Y< zi1&z;TUn)J!-B`lIQQ5%h0l{HjbHX=&T4J67iA`8RTQGuunC&<-j%!GkM&6VtguXKY|#Z}(@o`T6jZ)&FVpnnFj^=TLF_H@+4a6~}p2R`fnTD;7ra zcZRuhym@j9R3|GR1LU6)_B^+OpEjvu>7IQ0h{FD<=%H9U=<$tfef|)OZlBBonzwK+ z`_xDtrlUmpj)_1VPegzGR5zkRT)6_&AQq?mZstt>W$(M|P%3F*qRluF+FMyr)VzRq2$?BQE|z-HVHt>Tk{G9=kjXbD z?(t%7{T)<$gHAkD<36J~%?Na(eHyuXU@^=!)`gfv#j}3NF}N2~lYv6SUhenH>m&~6 zbG|_tg2beoHuFUqC9XjoJOtzH#%@jlcaksgqma7w2An~2ODST9b5l2m8lB11r0D!* zJaNf&`~DJS$+014I?ww1xrkm4NYw?E`Mg0_?1CnMS`1Q}Dx5SV`^<778%9Ft=Eju4 z!!IZ`Hs2TY?O9Wo#8;@aU~h7%6f8K-)F~E$A%l2C`ykbM7#=-O7E-jBz-Mtt z@KVLJ!b#`fMT(KKM;hBm*dNFC};Wh|< z5z)yOcXU4FSUYcj1gC#INalVoQKag042Q{tBNIO|mvQGQ!5s)p(D(5OTBCn2;-fnVu)=toP%hZ=7H6y};tW?S+1@D>%mj1UpZRNp|r zJ3_E$4zMAkAhBt|Y6mJ9!J>LQBJQLj;jI+EHZ-V1wF!56!*@&xqnWnoq>tyPn`?~t z<%P}$;2XOU9=!yLwcshWiZgqtukDtuatEHayGmDMs9twXc_zm1JT7rGuXMt8 zV5b>(4a98_6GIq~@FT$3N;u|7rNWJk#9a%*Lh*c3R0iq+zr7TGD?@!`&-YBU`DJ8< z`Je^V_0tqj7{O+0ha3E4QF?hw4!SItCw7`b2S+As9dhykcq8nzy1Wqz2y$T;_0+zH zHf(}toR?7DG>abb7~P9`*gl*r)IL^_a!MOr0>FwZ=E_5QMxsx>fG@|zo6$~?+PCB`WvXK1@To=xlyKt*l@=92n#SJiRW@o87WA(rrDQserud*e55nGkz} z#Njc>-hQ4PdK^DC<-9!}%l(}7ED<~f6FiAeFu&@+oq~sA%VgM(IB>gOqZPGL~4OAkZnDB+$x?2@Na+*X{^+X7Wv$zIS?(&D4B)y#G* z{}hbOu+zjH`JR@ZoFa5oZr<$G6b}B0&DaIG^(X&sN~luF#Y>&1ZHp15ekeBz(X;wj zpOcG0FWC@Htrc|kTe8a(;4z3MQR6aDP?%!_0HLoaXztZu23+NkX2iTusHWHmpM8Ht z)%L!`tXE&aUCG{2M`(ViB{wH#7!%#s+TBmYoE(+0PAialn>iQ5k^&?=!eAYnTWpcL zu$DruaSYwRvd3;H9yD%Sq`=azkId$h(yzUQwB~J@Q}JSRs5C_U3RynqS=T+Y(wQgp zH0-Y4J`{naEvyKK);vBo^@gl}RK&FhRJd;e9+1u&4|yD@Xq{&M9oaVjem)x)gytd$7lU=;RawC|M>K!n*W9FR zgSHjvuC$v}!x736De0HXDL7Gw&8+a>cZRyjnJG7?bjC;YFNTF_XO;F{E4k*~LPNHL zg_D(rE1(mwYJ8NFE=s9BzphnNFOOrwAotJ#dtz%9%t9t7p zt@mXxv45zyGnB>ARHu8&(LARBTuGsT89+YE-^JeLK1uEAyq0ydvW-`_miCfNiVZB~(yVYW&&+*mu_<4-XM z(Q8xHetSVh%L-=Sleqd)c7LrAB7_qj@UA8%OX{S&;YOYm2i$^JOa{hCkZ>XW>O~!! zly%Or7`Q~7Rz>70)fE0w!lP;~J7t4^pEVhNvszFU%YsiL6A=cZQ6;EQ?7l-BhFQI! zFcT4&Nf>8D^2B#;{`Fcs+#AvOcC~%HFy`j|jt%4BQ&ho$>^`!1GMgwE6_mXSDDuM0 zX(86NR5o33VELDmp2Y-%+&Y=e#{BO6gLx&NBqU{Fyv)@DEiI4SLTGbIbC!mKgf~ds zUb}plTrlhQ*s?H!=aJ=r7HK`Gr4zsJHEeTVlvh^1rKWa~(h=&_vT2G^)>m`C*t@%)`VDok>b6;zzmGwR$)Hv-Q98@i` zrU!4pBYG%^74mqcAzKk&iBB#9W?W~`*HH4nXHoNW5hrWz6Q4GL~!NytId9-lsKy?5=*Ytrp1e$hq5PthlRMO&O=mfM`Vi8V2xxdVs!wPtQ& zV6}+K&0lAE)P>H?*VAj^RC;Xt9XFVN(9d*#uykg3U)j2D)cuXGEfEq-)NB1V<;?OO z+~{afY%h0oCFaEG@NSi;00Au>PQl`50CEp}vz=zE4mpLqSlI3h9UtTp18Z5FW;4bc z$~ey5Ha_&2r;ne9=n_oa5l-d4+oq5(KShr;SHn^MP#P5Ez%}AflNDr4R>&if=yWt|KbR&>oSI>i$Jr-l$hJH+}Jp=npq%9wr zF$9pd`V#K(c7loX@q%o6$J6iKmUrbQl@aUW<08Ezv<$(Un*@gS(H(J{((l#cx;02^ zXk{7zbp5LLxX1QM@VukAWFJOSo(x_QMjF*owiS_km#*>R8 zf7juQ(OtxdeO}WSgvr3rC%5zaBKRFh7YEYtcx-cX!nlMn0xzgh8RYrxI~}F(k;&CY z)n|x3KiQICS19s#eMB6RyVhx}27X}X+R&>D>?psXe`)=AjkG+E5!h`!_IKfLRwJKb3N9a$RO%V?``SdNHXc9|C z;+iK_?!v^RBT4XIPiB0g+o9ED7@;Rbki>66xZ&>&jQ⁢Vk@8p#BwmAWGnPiVTgm zbEJw%_#4z=zIF-cVGvb}l(p+csph5JS5Y?Z3fi2+&=X%uTFn)@EW!8DSD9&Luc-og z*f2s2j{eezd-uczo{@`S2G;yAU?YnvifJ!;4ekiuktD^ zdRQi#5%b+4`3)~i^C9L|V8bIurmk&pM_uC*=g~V6V{vu(yF-sERN6irtNrN5tc)`*!0wbH!v(N%4T7F*^ z#Ny(8;x3S;VE>?m1EEchV#DUsyawIe@it_qe2W_|Li5;&b>{31?KC8{M%|+ zlV%~ocDgMq)6wTiUH)y=8HAY`plyd|`%W=A<)OE<>1_95!JC20BYc(_ZOG~RlzZtD z{bk4aa*VhJ%R@^IpYdN&rEipmd&uA61r^p%CT1>L_m8U-rD{7+vf&XNP=~Q581c02 z0!6!7!e-IiH_}*6?YZ;ZWY|ayjPcKRh41EeT7#HmYO{KBD!!e$XEWa!%JELvfbzmp zC{OJ%T$=M*VKhjgd^Gq9L27^$>Du`iW;#>;<; z+fzJ~#G9_*Fm%LW^Ad6VN7L<}{RFY}+fpHjwpAf*Idn+dR^Lib*4D}z;?k{b4gQ!8 z{KgT1_|F?~0|B(c_Z)$gIi-1FtQ^z`;}5TCl$6 zNWU6t*UVaukV>?kYIMj=@TH?Wd{jLtyCRTnPGYNl+_GHf*4F~c$iy|6%$YpFs1Byf zkT?^a>e7!Tt!4+xN6(ng=L9v{Z-t-~o@Ox(rJ2dDZ;k*oV-m(`gv=8Z?RNOJcc#W- zY|A4oB5kF%JMfF=WS#P2F?)I;FvS*mz)XE{_apVurxCnTogv-;PAgL&Ti~dj8d?g^ z1po%!pU^(YLs9c|zVRGMNmb$`A=@Udxc8MtwtZx)lb+YP6F9&JH}GDjDQLWj#L&<1 zHJQE$7jz+XntQ-kNXO!z)T3Yz?FfQU4;|uYfPbZ)j%Um(sC+*?Yd^QG zro0N{n-;Np{qCD(p|3Vo- z{yWNl=x#p*eApxY1vvQl-+TJsI>rwHAGTe80ro>mTF4Gx$NVIeI3(J(*(7()y}mFUOQ{{XxzS=0ak literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gradient07.xlsx b/test/functional/xlsx_files/chart_gradient07.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..9dfe0b9681e439ae00a8595cb0d5dc1c575fde22 GIT binary patch literal 9405 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 IlKy!5AGatsZvX%Q literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gradient08.xlsx b/test/functional/xlsx_files/chart_gradient08.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..79deff89c6d09bd85befa602191de27fad9d92f0 GIT binary patch literal 9387 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gradient10.xlsx b/test/functional/xlsx_files/chart_gradient10.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..d33bc55c5d76822603e43298af17a9d484668b0c GIT binary patch literal 9373 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gradient11.xlsx b/test/functional/xlsx_files/chart_gradient11.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..73aed36bca6253bcf038052372c5f327847683c0 GIT binary patch literal 9393 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 XuPg@-W$}-?9}Qp$H3Ty9A5Z@SdK@ka literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_gradient13.xlsx b/test/functional/xlsx_files/chart_gradient13.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..981cd9cfa3daaf7521d3ebc09b25cef9708f8b6e GIT binary patch literal 9389 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_line02.xlsx b/test/functional/xlsx_files/chart_line02.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..842fe30a22c0b43d4907cbe691a5cedc7b0aee20 GIT binary patch literal 9295 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 OaRBBBLl~y|arZx+dIUKD literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_line07.xlsx b/test/functional/xlsx_files/chart_line07.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a090bbe520f49c3501077538f0df6d5b4f5d8df6 GIT binary patch literal 9447 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 E2L+)*XaE2J literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_line08.xlsx b/test/functional/xlsx_files/chart_line08.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..50f2dd49d31783fe4edb13fd25878c19decfc32e GIT binary patch literal 9446 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 EKL>nE?EnA( literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_scatter07.xlsx b/test/functional/xlsx_files/chart_scatter07.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..76b387f53bf2f0c50ab870664bd3e9a5f6b92e5e GIT binary patch literal 9400 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 GJpB(g8bOu- literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_stock01.xlsx b/test/functional/xlsx_files/chart_stock01.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..7f0c3681ac4a98d7332e0b2f755693f849cb7af2 GIT binary patch literal 9586 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/chart_stock02.xlsx b/test/functional/xlsx_files/chart_stock02.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a29fa0893c7431433f9d97a196fb7b321170e48a GIT binary patch literal 9723 zcmeHN^;?wdx}E`Pk(Q9|kgid>Vd#_)k?!u41_{ZbL%KTz5p?Jfq*Fq=yCl!(+IzVc z%YFWUbN2Vc7uPq>ea-tm_tT$}Ec`uO03rYx002+`P$fwZY=8j3)ja?J2QUZJ5wo>% zGPZHjQ**a7cGP8Yv$i77o(9st1;D|6|KH>P+zyng^(nNmVSb=Gz=)}!x9 z$rr{GNdr8!S9N#@bzhFJfi7l|yn};y`Uhfir>!}QoK>kVcO|Bp?~TaGP7Lr#;JZH! zKDv1k!s(+&X1bS$X4m|^;M%O@);_J^)x@ztrbQJugTB?q%DG{68* z&%xNrk(K4gnLNAqzee|e#@Hfazrc*_e&?R_2eIYLO&e+Cth^>U=_U#_(ofX8WOb1_ z)WT<{f$;ud!OX3rRSC#pK361Sy&w&PV_$hipqeCL=hM5VA~-thE2Iw-)tz3u+aEx{E9&EM^Ytb z{xPTpGLk1!vET*&_v&|C^0scQtKJ5Q3K7B?IDCCBD`F;SMPFtLQ$+h@0`QK~MzDG= zDGlK>Xs4em9^cl3>?vhm4@xf_@y~}j3U6)sv1FPRoi`8gFBSxTlQ%lohjw77>A}?Y zPp(IXOxrEM-Y~>RQL3dYM2TKE6TgxAz=3msm_k;Sdp!EOyD2?f}fO%$# zv!I)RByRy1)V%oasd&-)j%xr#6j^&hph@ibE4^?2v%=CmQ^@6rvyRl(u0l(16>uBR z6vSdy-gay0ot2O6t9$b|`x~&A^8~o&>Qe^mem}3g&V@=pZPz8!%zM~H^fYEaxVt`Q z$Zi$Bk;~kRI5L+&=YA)toNPnS5q`ui-&_7IwM%WWuM=P17Bf&E?%2$8HRrk7Mo~R! z^c7Apm&R9uyk>qK{4tG2>Qmo&zraCkMv%q@vHgp1%Lg3-BrV?jc2d+OUDX{R#fOCa zm&=FvzvG8e&)T63Oy{^Teqg{9597yQnGq55GfYXGNnZtUd!~e>#B0biQV2T*MAPp~ zx5srB8%ov7PJc8_V?=N%?L68)_`0>SIm&n%G%k~aCQZxEHVVN~*+V;@!Ux3=Dd=x=IkoSPLJhEMB}Kg2t$ZLu_3d;5G`<=bg?=s~&X3iFP)$|qdc z8yV@SY+r`F{4OB`&u!8-DnT|6zmPLlP|iQb(LBmId=$$&+*9F{lJA~$U&D&#bazcf zddi%xj?Ejm5nn10r4v9oyTN|TAP?g>-AnjOImX$UKnD%SRiZW5YI=l--C_> z3Np5H?bkpzmsKW9rEIuN(FshMA@c{o%lxVOfIm?w}2MQgIzJyI%tU=^Vf$KOrrz@ZQ@JRU8 z_qW^C-__^*KT^Wi6}|I^}Mi0?C=027QZ1FW&D z4+?B;S^WJMtW6WIP4cIO3Y5Px94@2>t2`v{CbUJGFmK@M8hdz;&gr4lo^+es{Y#I= z!T~OWUd68%eiHeh@xcOI7jV^vxoCo5bYJ3l7m8{^l`60wk56SQd$RDn$M+(fK|w=| ze+pZiGi3WJb7#hd&1rv?Cq`E2aeU-?cRvTVp_EKO{2s~25S7*Lx0_&Z_0r$R*o}Oe z27g2VK=sj&V(zC8buu%yHfH^K{<-9BEk)ZI9^8)@ldj}Ww$^m@kC2?hCaY4*3lGb9Kbl_h1-8A{PXspYuvsw;!ZkT%(&~hi!C&B=N`tEj`ecU@AB~TN zh*Q4ux}9I5az2?32+b0sq+YR~DbX$W2yGW68v&Vlx&~j%J|c}p?K1rACO18oCcQU3 zez~XHk;+JoB~mGvklL^l1g1%agdOV>^!4#muz!|s2(9#ghNadCM+Te?RUa=NGofka zI#r6GBKP#<$PyG0lOLYx4Lu|H&NI^x>k$ zhz}u1K&732F?RK#cYF+WP7a^F&cIq6lN-shxS_|s+e;ifHg(EnP3LgeCp5`A=?VoyVB;!r^lriN z#QjHOCf=U?&_~f7yb1d!11|4ooc0lo4*F@lZows5t_O&?97KwVgVR~pK45_mInWGq zkS)L~C#4miJ~WvBJy$qN)L5}*_`WyG1z=D(7%ws=h0e&|J9LrdjikRpKfo6Ic~X^F z%X6aP57Ea6@@g}eY|v;dG>?jmSGSwrRgX8n$1R0?c|&&NbhSQo&_>40Z2FDmO~7Jn z;=Ir4+5}mSP=?RZ;Q{`Nn^ybnMH}76t1I^>m>gylL*cBMSEt)O;T3|{*G*kC`__I^ z66ev9;@LXO$Rzv7PMpE^G;~zS zbJo>}B+ww=3}x++{xaYUWJ7t^eFB6ino0lq&Umz}uwz0izglpR_6QHASBvn$t*B;~?R z9>h7krTTa1I;vXW?F@QoiQO%8j@$7- zBO>Z%cM#JWJKVle>QamG(-uY5&h-fv6Ve%18L+^UyMVoNzql7@mVGMA>uCYLs{s{t zm$&%qt~T=?s62$Cv2J`2hYVTlN@ITiB z@OCDxhD%Pntw@n%5P*Vu8H0*IajBFbcbqO-ny{;zKrM@s9LgBVgu`?iN{r1j%3WD> z=7JG~xtX7mYy4?Jp)>O`!(@mXm&ETz_QH==6)k<0W81m9Sr?I0bUqJ+7PO| zRsP0#X)kJ9DCPsG!-Kv)sAL?vt@J zy7$chsu((pL1ExMtkJ16Z!YzUh^$oneXvG5i&>EYxSIU5X*Rub81!N_(v?7K$1|ke zz$M<@%hVKQxu=2tXgUDnK1xPt1Swrv2Bi;}O`VOQG-mu0TjN;|J4eb=sl6a|fi%q; zl}ap76L}j4=n(HthvjUC^uBUR@Bs| zUSg*JajvA(c!gsUZ>FeqX2Ra?aXu8IurCo)Z(S_V_hV^~$Dix#5v_W7R-Vh^rJ1CQ zpK}$(Or`DT%eKyE%TGRz?#hbSg;!J4@DcA={vx(vY(ef zk`v8&$7v9z&&T9Tvge9=mR1q$Y(Wa5wCSlb1?jRgA)Yv=a4p@jQrIZR6(7ei4CU-w zS7I9z4*~Tqb=uxdnJyid7&EaRXXHlEsnIC^!82cDe%48g%~zKm*EY+ZDp(0Py@Ybt zB+|ES+h_B0rg2vCf$z(t5lM;k9b)CL>r}>aC*r1vz?ASWfMQdz;j#2ycqK1by5Wgf z%`3=)+cMY}`QVoc5y2{z9xWhKK|Pl6`{i!+41Nq-K>#o=CHaH|%{8IT8|?bSU6k~T zPjlW)C!QXIpb|31-mxHn0k^AHPQ-J@jM;wf$J*o~>zS1E+G1JUtr8EixhYFn3uS2I z-7!=@3W103d6VOGR-l2092EQZk*tZvtW>b=P5b+F8y5&fcNp6+Hzbs*l)FO@f~|Xn z^ovNe2W%z)j2=g)i`HDw3UNg?O0^W6h;(I6k<=q%6Zbi$zPSfNk~LUn^rLCEN!1Ui zUBV%Ub`z>XTuO6a7VSY{C!?NAI>yAskZkxokwleS;hqN1UKOvmT-()LASLh&c>N{3 zuQz-2w;XsZYeTqwX)1Gtmq?*O%yiFb|oPsS@ z|7!WPl%%uA4HO!jz`1kaly(xB(0OC?sL=RGvI>T9gN>0Lyc^ll#*(!)cG zTU6638Ik6^q+uF|tS*gN9v*)DozE+*qv4TYD4(BxQ1qHk`3tE2L~{(i&`LK-4*b=xEV4 z#N(I8jXjuIEeb2_dTKS3<(G-QVX03r&L$JE~OTFx+Xh6Ad)|={bsiQofzcs_U&_s!}m+DxZ@emyQLJ99p4*I z7X6l5mf}jdge}LQlmdY-x}^;E_*!YE+_mNP`_0jrgtH`Ugz71MmGnvP5%Ts&V?BC_ zkYCtWJb6YgH=+`Q=S69t&bGn4uT79E<97at{y~m z9bD_oyrqf@3ul3n!bTpt6yUiXoU5hFkpgZ>@JM-Xvdgli!fX>}b@Ag;_&n_DJR+Z!Ipt=f+FAwcrSo#nwc2=Bw}?u}EsmHP9;+rx zm{{La0mPWnETVJue$SwhhUK@(@Dx48_k`SL_}dkTWxjUm=t_nwDtD>B zjJ-@?3~@ncdEI&$9)YW9n{?WZg_|Y8b0>OCNeJe}F?@hF_~|FKkmZE7z`nKN8h9t4 zk>TH`FjKXHfNkD)W@wWG8k}AOCp`Mb_D3`@Cr#dtqZ1 z(8|N4iTck64agxS$wwu2OV$XByPA?w9u*E=4ELlH8|nN)MNy|s1(_=1E<;YRAzI*S zP;=zSM#^V~o^_*(xq<7k`TR|?W%CQ6*PP&dCmz}ipnhX`rjidVLH=j@Oa}^Y4~6j# z3-%WCue{T@v->aYeh}`DBP|wcGsAX2cn|*cLGW&5+Dn39VGZS65|7DBfJ{>j?MRi9 z7Pk1f^yzVqb*}yU^n9G2%=44i@$Us(TGlCY!n3gZBp6VUdB$0Y84qf2J&q)BrD;by zy8sXnFihwAAYghmi98Pe@g(I-8tv@b1Z-=xbSOffAB1*w0JGpbx#0*1?QE#U1yj1b z_pm0AN~AEWMaDMRz~TAX@yC4UT6i+SJ;m34b?;?+_$)*9iazqCQgsH0h2$VqEI(J1 zdk24+LXz%Ow9K#0XUT6hsma?(Meoi~D8<$`Sl?+pT3q0akzl|wc)eOxCVtRIejfx` zmv^DXG(@*n<>(ZoFuvwo#kT??LzaV!K*2|I?%RSJE0dp~&Py-Z{3`7t8(f!xuefyL zHptrho*Z+g@P!qVFo0i8gS(=43(sGo<_~|0{-X@Ni*Pr!{Dsg% zbay*`C7O3p{+=TI!TF!Pe$&v2v4(UOx{0wmus=y z=MOk%e?QDO-}TOOU-Q1t{q(1%2nUY`Km;HI003$Lstm=xBM<<%f(HO_0SiDwNhe2l zOGkGTEgxq~HzRg$2Yagg86Z}H<-QwV>&c27gg_wC(jkOMtdyjEd4NT-flu(tN)$CLQJ1}rr}!y1=|=EQniDGg;w z0S^`rtWuND zo-{|ea^dk^9+^hwTZeow9qnV}#i|Rjr-P+;!(zIH)xJrQp@rWd zMlS2HLOV#$O;_6>#MN~aOEKY5o-ksxL+heDaKR|G`EPkf7Eq_nmYC3Me9yq z@Zb>uu`1bz=+QLqf5IH>wtv zU<_Y8J@CXu)0F_~vzk&1UCtwadoR^5Bn*o;bHhXY6r#D>lb&I-JF28OIVdPi=pztu zcw-#N9cV&nwOfeh+BOx0zd|O+jIOucP}SbJ98%|yC0$EU(|>HL48m_MxK3-u~6qlqv&KdZhjfXWGU8ByvL67-M=B<@A@HoP8o zUWaSqvGFI1FCa2R@1{^vZ0tKEjJp-g724LiG?1K|{G9uSneJf6agnFB(97vL?W3lr zVre#VglehL527R9XVS~I51f4x-cQO7*SR2bF^;vn|3R3%EkMXwmaeR)<^xETfLQ2q z^?>kq{GhfJ?2w1)91q41Oqk+f{P-&~;?(~PQxgj|6b>2&yrp4)VKj;SIxAc!lCo#y z)Awy|vz6cAHM-1X1;lxEmmQbtd_${9ma)Q8mM|?rqb(2t??D3EnvvFpCPP?XKMds- z(A#*+Up6?kQv6U>27bm;&1aDhLRVoq5p^p!v%g!dGFhuS$_n*DM3rX7Bl*$YJ8 zbP{%S#Y@WjnrSudvYK_gwn5a8lE&ggBYIM#^EWA|UWC$d{GV8>w!SCdD{4GcmGH$Q z{)qhQ{w<#UtWcfC@jRUpRc{r|A{(yWfzJ7ZKGNyFDsO@w8_{V)Nb*!uP9a6jsIjft zJM3#*%+#D$Ipjodm0c#!pOc)77uB}IHebf&Z$}V%np$L6z)+f5o%;4R zlji|kaF{3Vbk9B{V7c50X&#a#Rb0;O6WF$-L}F%V*+3uU7XWJh^3jKr*L|WlDM+rz zscba)Sj__BMGBTOeJt+SXSjPwGmvRri0I|$XTvn3H@4LG!9j=iTeN}Kv@4{s|M7Di z+ew8jev2?h5m1P7C|65N)_H4dx{;Tal$}c$Nu6(9*v^|+4*~|{CrVT+O*U^npd)d} z41F)lz`nm8Mn1;?T6h+hW7(2bS|*eeZN<5|S~mXmAU%Iz?Xz}Om0a_qBYmGYZ>2X4 z=_#=4z$EZ9NsRg*zb}gK(KFL#dvf$@86D7DMbsz+F5dG^J7n{?JbIA02io}@CK*b{ zi`QT?rRF+Q`rKIq2hVj+DK7WLkQ^_4;YsH_*s&eXPu8PLA&L_TgCoYea1BS6n?6Kz zM?kqMY))^#vT%Q;Dx0Z zP`-nUYZ?z*ms;wqvP&U~g}}1e5gX2jnh0u{AdQ$$V%#;JTQW2rrsV_+KiGSmU5 zX200Ui9IA_$-yf9`bp7@XtDYn^TAS9ga!dsFR>HSq)j7F&o}`*qdS4@u3V=Q`lWAE z$smt;zv>)juyhes$09r^7lXJ^)v(|vE9FHupHEhYY}_Y)V6g{*vN$}ai)NR9R0+^-4&+U38GvRg&; zjUk8tfF|jWa_*-Wb+@*3u;lpp`E$$P^i`c^`S9LjPI*zeJ2@~mkRo}+OhGa#lu5fB zBPncNrs-+si;c(!kj|_;1$MqOO9wXZaN4sD-D`HwVK9uWfV;pykyEH48c-ZTB%K(K zl%fgpzg=9R^*Ejhjmndxp<8pAEi!MR+?GJl-r$| zxZE}RkikNSEnY2>meIHqu0WrW8gpbuG%z4U{qUo5V^npBF1A+pJxbtwl=j4%@h9{h zJSS>#v{Zh6TzMkmlFB2q{ZXexE!_%VfjQB^49c1Kh=SP@JQ9PJ=_u||`m=B%7J)o; zm?@D&X{Zb{#^YBl{S)J;3rd6!>&+d^j25p(Jhnpi-9PQ&L7A)!wkHjBJzXyl+sC*n zC$~NP>NB%}ri)0*6>QS4j&Ectl84!zep}(%ajaLbXg<4leN6w-FiWL)Siuq^h0!ZA zk-kSd{v^Qf6O=UJ1Ap4y@u271S@%6e@ct)y|67GJeXo5)JT4N|^r4x&>p%tJNF~th zgK#H+|La#BgiKKpLhpEDQJ#;#(Tm*+V7~wiiACVYC%$3?hXh0|vp4x zBH8wsWTYkG2tiqE_L38tfQ{x`l^t~Z^<4Al>v{4@yQ*c(O4``C2qP@bF-taLrr4>-M6P@%`16&m$}@YwF=xj-0ELZ+)>OZPB;f3PSN}TY@%$o0QAB-{LYiDjQJJfNmN9`K*3$+) z@MZcIdZnj*trwvOh;`IAlI)$F9P&qnFiM>D7yAO)%w(yFWXnt-zVeb0u!OI;&^d6tGk3=!mUmNI~k%6^HmqsTO-avg7d<@Mo( zdPz4Q;sX9k!&?kPO?`!L*-X$f=UZq;bEwt6NU)yCg7?DsyqCwM-}d(RH;+Z^>W%R9 zN?PCfR0lw|l3u4OAB1u7skzBGDvUBJPO)_d5RGkr1SYOV7SV>f+?EUZD@j(ZjTS2uZ5)SqF{j@v`4DQqjKrAmK>#YIYM_+Z+ zDY+mF<_Uf(q8nc3_GguLeP9WHZFf&IsoBA{qQaEVc-W!N{$Voq4EH%3O(Iz~xr=Zd z8I`1mIGj_9DjbUDmNOZQ_U{cWeFHs_j~aC?)8rWdqw)J>4wx>WE(bdn){w3ZR>jDl zqiGZpb>DJp9|hi+qm5!|Ip^5l zpt+XZ&Suu~C>eB?s*(=@P*5)uQ4y#w)zXxXvLwpWz8j^{DWbfLVu@nKWj%=^!{Hm_ ztu8(F#0_!vdY87Op>JCRz9Sgt-&4!Zl<*fv(X{&$!BS{ zY3&`~TA^9L*qF^|=?v}9HTPcNH-zZCI;mprc=Xo55R%4YYzOWLCQRpzfVNO8ER7&- ziB{jLf8oA#k#H)J3W~&lh;8D33Dv}!v8uU$^ zi!%;|&Fmjc>t6+^SZsWHIWXAwA(qF})~sj3)4s42TFa=37r`(s-VN&ZA7=^lUVeSK zv`OB$ob!-gnGRYl;BNgv|8?XTg6QymiVBG{uK{5UaS#It=_Lgox z^3D`ZsO=mlRx8p4ro^etb|Hp5BummPZzw{HFQLr7&loDlHR7$mvCUmWKI>=e2a#EM z$?vofchD1y;5k7}vWuEM{~a`1dD7q5uvFF4Iq5e@qfkueU5qBO*-JUV!SB-rJQ|R< z1H*qYhpI-+V^W(3jOcV5F51Wjkx-UPy^GN4Vz(|eSE!*nX`auj9swDz$9oa!@AyS_ znR}-A_*+?_toAiB9nOSeqN8L-#ZfR;WYYvHaB6chmnTlNb2gp!J>+_|Qtl!`S1d=r zL93Aj)I+{vC#E@5v%RiaDF!dMakj*kXf7 zQ$Lw|s1(nOlN6OB@&MN7n-7TldnW`@z%ifWrgJ@QG4_%ejwT+PnUJje`cTD%D#PZ|VILifgI6(TzuZ4YhZ3ZmC# zVp-|avh@t|LqrR~ORUc0q+%-sX=SKkrR-&u%{)3O_`;C|XBy$F+V2vDmt4;E_r`Bt zr*7?Z;vCx#QpiSyRGsYd+@*9)YUQZD6=yv%2ry`{7-PpNW=1WrhS+!ow+`bt*hwbdlkYiszet=^!^Wr( zN-!;%Kt_{v2qJ6!g8L}&G*I{9?lT2#RFUHqssrJEH}w>M-sAT{&Ax&s!i6Xt$hes* z*TUL2m(#oNTL&1=U&#e%CTIFCg_X&R98VfdCUa_?ztWLH$S)$ZSEOdm&tug!qwXWf z)MZo3w=2h$SooN(`jR7UfU7v2W>G7}jx@X=&e~M0V!+^>+xwBsS${LF z{a4MKlgoI@WF@7=|*ILp_qyikH6-% zd^*vPt7mPIR!>mNqaa+>C6fr;I219rdrjP&$#qRko8?R$Z%|M7tP(1Kr9*CzFEfY< z)4JvLNKV4Xw32J{Y{IeK%qp$ika31wL_Er1#DLsYWN=47ucj|N$%zjMS+I-|7W@>B zsbB<`wE#}AWx+Z%J4eDmET!9dqALqZXKDo-dZ#KKmwYHxpWpi9Q_E&*E)ldE<7Xr^ zD{N88BB~gP`%FZqMFrGc6o^|Wo7glMp{8ETpm8~WRa(bYZQ2qFyb+X1hntKsniBq7 zWn1i{_jcfCBriqZ%E*ZCc01A~fyKuz#cjRe$)!bCA4Y%Qx#6QlijE7#l@+Z@Sk0E0 z>n)Qoek#GPPM!X_A|X96rr?xkS;m<6;2zHbkoVwA6K@hiXtI;%rI9EZ?G`O#*B2sU z1e@L9F|r=#xFZfPkWBk%-`4Gs8`#J=cE_Wyl&i46s146BP`sc6Z6{_dC_UVG*3dt* zNyAc;wtWdLvSD1>i*GuBW$s#3IiD^bQ735U%o!x4I692gvwtvInv9yib$-9onh{Jc z%fg6mD-(vSFERckhPN54eefAP333bupK3Fq=}$Q?O$2J&RJD4jUN=++v*_A`Rf6*j z4aDf}H#WK6w;ET6vZ{DpWK=giMlBpPa`C!~P-D-Hez(>q6B|_GUR%9k-QYMC5}?nH z??JCcMtl%lm`2#hlY=v6v`dI$&X*K(#kwl1PaxJX%Yf;;j{3rczC7cLEHZZy+MBm2 zuIZ|?(A;1K+52?@+K-IXjhCL86?ydLx|ieX)^`fUim~~gm1&uPW+~T@sT|fg6f2!d zCaNjp-6vASgoEhAibj|U8CWk~_G62TS$Ny(LqQGT;ToBd(vPSr`9r2gq?N`|rr={%l8Wt9+ z>TaP20iSf4>JYaJGfWd8>8v;G8)5`xfr{8A-7!7yQ80TmT?KIYRr|Wdx!eqbrp{7 zdJ=s;7_gx1>LbbZNh{)$eOO3rHLc?;XmIhLY;`j*@S1v}7kk?W9jF=9?>>|q5U@-} zo=`)$u+%=qDRxnZDJRyOtgS!XlV-)Wy12$7B}A zjLNW<455%2jHeUQbBEcWJ=YNOcq;ZHc)!d-*<5Ms$=6ofYng|5Oo@b3`5xrC%_Up7>_pw|eAydWe;~81Dw$ zp<*%jD5F+9b553#!D6;S-tg$5#0~m;M~dtVZHv5jh7ZL&`iRX4N+uiHCXuw4_45Rc zC9@X81b5;0GDbHaRUxTR`aK0cm%!rcy3sL?nQh)78TWZb=#tibZl1BR%0hpBY{-A2 z8$@W&)a!C48jaAWp}}U=Duq=(m235fs}M1zW*}r9)VMrJb3x^M6_QgKvLa znMqK`Sx)qbUAU9`5#Qr8O^G7JbkqyTeW$7c^3AmjqYyQH9H|MplcU!T1upNhig5dK z&W@u~-U)lQZBoCE&BGaxW=2Kkn_wqn*{{3xJ(R|iV;Jl10i=R}F^1Rsp)>0*sFLB> zrf5v*4f5;Ka2(LGpa=uOsSN9bSjFd57Na1v)8RHxEV;`5gW51!@shkYd8Y_-*T<(v z?~6R@;3!3QRilIJ-zoM9+C`a^z8B1(?T(0ve2q}G`dCZpE!^cR@+|k#RUvIbJ0bfi zJ^pT5CLiV!S;ebWrN1vL^$U1%`trSGNeY)-d^yhEa<_;-N6Prm;x z_~RY`Gl{>UBJ8DpF literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/checkbox01.xlsx b/test/functional/xlsx_files/checkbox01.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..fe5ef9452c4279f5ee9388b23fb62637a947f8b1 GIT binary patch literal 5589 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 JKV4hE{{a&|bD3 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 literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/sparkline02.xlsx b/test/functional/xlsx_files/sparkline02.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ce343b381f302b6da7ea380d5727f8a5e65afb36 GIT binary patch literal 5166 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 LD~WU5CkbHm68q#W$5Tsn1nJ3;i0=r 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 literal 0 HcmV?d00001 diff --git a/test/unit/chart/test_chart.c b/test/unit/chart/test_chart.c index 67f622a5..d1f94d90 100644 --- a/test/unit/chart/test_chart.c +++ b/test/unit/chart/test_chart.c @@ -142,8 +142,8 @@ CTEST(chart, chart01) { lxw_chart *chart = lxw_chart_new(LXW_CHART_BAR); chart->file = testfile; - series1 = chart_add_series(chart, NULL, "Sheet1!$A$1:$A$5"); - series2 = chart_add_series(chart, NULL, "Sheet1!$B$1:$B$5"); + series1 = chart_add_series(chart, NULL, "Sheet1!$A$1:$A$5", 0); + series2 = chart_add_series(chart, NULL, "Sheet1!$B$1:$B$5", 0); lxw_chart_add_data_cache(series1->values, data[0], 5, 3, 0); lxw_chart_add_data_cache(series2->values, data[0], 5, 3, 1); From ba048905125945e57f6a8f5038c7b30d5f8166f8 Mon Sep 17 00:00:00 2001 From: Nick Date: Sat, 3 Jan 2026 00:40:38 -0600 Subject: [PATCH 2/2] added missing limit checks and improved tests --- include/xlsxwriter/chart.h | 10 +- include/xlsxwriter/common.h | 3 + include/xlsxwriter/feature_property_bag.h | 6 +- include/xlsxwriter/sparkline.h | 2 +- include/xlsxwriter/utility.h | 24 ++ include/xlsxwriter/worksheet.h | 7 +- src/chart.c | 66 +++--- src/drawing.c | 3 +- src/feature_property_bag.c | 2 +- src/format.c | 19 ++ src/labview_wrappers.c | 201 +++++++---------- src/styles.c | 2 +- src/utility.c | 262 ++++++++++++++-------- src/workbook.c | 13 +- src/worksheet.c | 11 +- 15 files changed, 346 insertions(+), 285 deletions(-) diff --git a/include/xlsxwriter/chart.h b/include/xlsxwriter/chart.h index 3c6e2285..d7c1c9fb 100644 --- a/include/xlsxwriter/chart.h +++ b/include/xlsxwriter/chart.h @@ -735,6 +735,7 @@ typedef enum lxw_chart_gradient_fill_type { /** Path gradient fill. */ LXW_CHART_GRADIENT_FILL_PATH + } lxw_chart_gradient_fill_type; /** Maximum number of gradient stops. */ @@ -1461,7 +1462,8 @@ void lxw_chart_assemble_xml_file(lxw_chart *chart); */ lxw_chart_series *chart_add_series_impl(lxw_chart *chart, const char *categories, - const char *values, uint8_t y2_axis); + const char *values, + uint8_t y2_axis); /** * @brief Macro wrapper for chart_add_series_impl with optional y2_axis parameter. @@ -1707,7 +1709,7 @@ void chart_series_set_pattern(lxw_chart_series *series, * 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); + lxw_chart_gradient_fill *gradient); /** * @brief Set the data marker type for a series. @@ -3812,7 +3814,7 @@ void chart_chartarea_set_pattern(lxw_chart *chart, * For more information see #lxw_chart_gradient_fill_type. */ void chart_chartarea_set_gradient(lxw_chart *chart, - lxw_chart_gradient_fill * gradient); + lxw_chart_gradient_fill *gradient); /** * @brief Set the line properties for a plotarea. @@ -3885,7 +3887,7 @@ void chart_plotarea_set_pattern(lxw_chart *chart, lxw_chart_pattern *pattern); * For more information see #lxw_chart_gradient_fill_type. */ void chart_plotarea_set_gradient(lxw_chart *chart, - lxw_chart_gradient_fill * gradient); + lxw_chart_gradient_fill *gradient); /** * @brief Set the manual layout of the chart plotarea. diff --git a/include/xlsxwriter/common.h b/include/xlsxwriter/common.h index 2b793223..f7b281f6 100644 --- a/include/xlsxwriter/common.h +++ b/include/xlsxwriter/common.h @@ -110,6 +110,9 @@ typedef enum lxw_error { /** Function string parameter is empty. */ LXW_ERROR_PARAMETER_IS_EMPTY, + /** A #lxw_datetime parameter has a validation error. */ + LXW_ERROR_DATETIME_VALIDATION, + /** Worksheet name exceeds Excel's limit of 31 characters. */ LXW_ERROR_SHEETNAME_LENGTH_EXCEEDED, diff --git a/include/xlsxwriter/feature_property_bag.h b/include/xlsxwriter/feature_property_bag.h index 5e203c3a..cb79eefc 100644 --- a/include/xlsxwriter/feature_property_bag.h +++ b/include/xlsxwriter/feature_property_bag.h @@ -39,10 +39,8 @@ extern "C" { /* *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); +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 diff --git a/include/xlsxwriter/sparkline.h b/include/xlsxwriter/sparkline.h index e99469ac..6f41a2f9 100644 --- a/include/xlsxwriter/sparkline.h +++ b/include/xlsxwriter/sparkline.h @@ -160,7 +160,7 @@ typedef struct lxw_sparkline_options { /* Internal sparkline structure with resolved values */ typedef struct lxw_sparkline { - STAILQ_ENTRY (lxw_sparkline) list_pointers; + STAILQ_ENTRY(lxw_sparkline) list_pointers; char *range; lxw_row_t row; diff --git a/include/xlsxwriter/utility.h b/include/xlsxwriter/utility.h index 6653f1af..80f2e2ef 100644 --- a/include/xlsxwriter/utility.h +++ b/include/xlsxwriter/utility.h @@ -212,6 +212,30 @@ double lxw_datetime_to_excel_datetime(lxw_datetime *datetime); double lxw_datetime_to_excel_date_with_epoch(lxw_datetime *datetime, uint8_t use_1904_epoch); +/** + * @brief Validate a #lxw_datetime struct. + * + * Validates a #lxw_datetime struct to ensure its fields are within acceptable + * ranges for Excel dates and times. + * + * The members of the #lxw_datetime struct and the range of their values are: + * + * Member | Value + * -------- | ----------- + * year | 1900 - 9999 + * month | 1 - 12 + * day | 1 - 31 + * hour | 0 - 23 + * min | 0 - 59 + * sec | 0 - 59.999 + * + * @param datetime A pointer to a #lxw_datetime struct. + * + * @return A #lxw_error code. Either #LXW_NO_ERROR or + * #LXW_ERROR_DATETIME_VALIDATION if a field is out of range. + */ +lxw_error lxw_datetime_validate(lxw_datetime *datetime); + /** * @brief Converts a unix datetime to an Excel datetime number. * diff --git a/include/xlsxwriter/worksheet.h b/include/xlsxwriter/worksheet.h index 26f899d7..6fd82c0a 100644 --- a/include/xlsxwriter/worksheet.h +++ b/include/xlsxwriter/worksheet.h @@ -2983,7 +2983,8 @@ lxw_error worksheet_write_boolean(lxw_worksheet *worksheet, * */ lxw_error worksheet_insert_checkbox(lxw_worksheet *worksheet, - lxw_row_t row, lxw_col_t col, int value); + lxw_row_t row, lxw_col_t col, + int value); /** * @brief Write a formatted blank worksheet cell. @@ -4154,7 +4155,7 @@ lxw_error worksheet_insert_textbox(lxw_worksheet *worksheet, 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); + lxw_textbox_options *user_options); /** * @brief Merge a range of cells. @@ -4651,7 +4652,7 @@ lxw_error worksheet_add_table(lxw_worksheet *worksheet, lxw_row_t first_row, */ lxw_error worksheet_add_sparkline(lxw_worksheet *worksheet, lxw_row_t row, lxw_col_t col, - lxw_sparkline_options * options); + lxw_sparkline_options *options); /** * @brief Make a worksheet the active, i.e., visible worksheet. diff --git a/src/chart.c b/src/chart.c index 982e0c4a..4eb52eaa 100644 --- a/src/chart.c +++ b/src/chart.c @@ -324,10 +324,10 @@ lxw_chart_new(uint8_t type) chart->y_axis->axis_position = LXW_CHART_AXIS_LEFT; /* Set the default secondary axis positions and properties. */ - chart->x2_axis->axis_position = LXW_CHART_AXIS_BOTTOM; /* Same as primary X axis */ + chart->x2_axis->axis_position = LXW_CHART_AXIS_BOTTOM; /* Same as primary X axis */ chart->y2_axis->axis_position = LXW_CHART_AXIS_RIGHT; chart->x2_axis->hidden = LXW_TRUE; /* Secondary X axis hidden by default */ - chart->y2_axis->crossing_max = LXW_TRUE; /* Secondary Y axis crosses at max */ + chart->y2_axis->crossing_max = LXW_TRUE; /* Secondary Y axis crosses at max */ /* Set the default axis number formats. */ _chart_axis_set_default_num_format(chart->x_axis, "General"); @@ -511,8 +511,7 @@ _chart_convert_gradient_args(lxw_chart_gradient_fill *user_gradient) gradient->angle = user_gradient->angle; /* Set default angle for linear gradients. */ - if (gradient->type == LXW_CHART_GRADIENT_FILL_LINEAR - && gradient->angle == 0) + if (gradient->type == LXW_CHART_GRADIENT_FILL_LINEAR && gradient->angle == 0) gradient->angle = 90; for (i = 0; i < gradient->num_stops; i++) { @@ -2302,8 +2301,7 @@ _chart_write_a_grad_fill(lxw_chart *self, lxw_chart_gradient_fill *gradient) */ STATIC void _chart_write_sp_pr_with_gradient(lxw_chart *self, lxw_chart_line *line, - lxw_chart_fill *fill, - lxw_chart_pattern *pattern, + lxw_chart_fill *fill, lxw_chart_pattern *pattern, lxw_chart_gradient_fill *gradient) { if (!line && !fill && !pattern && !gradient) @@ -5575,13 +5573,12 @@ _chart_write_stock_chart(lxw_chart *self, uint8_t primary_axes) uint16_t index = 0; /* Default line for stock chart series (width 2.25, noFill). */ - lxw_chart_line default_line = {.width = 2.25,.none = LXW_TRUE }; + lxw_chart_line default_line = {.width = 2.25, .none = LXW_TRUE}; /* Default markers for stock chart series. */ - lxw_chart_marker default_marker_none = {.type = LXW_CHART_MARKER_NONE }; + lxw_chart_marker default_marker_none = {.type = LXW_CHART_MARKER_NONE}; lxw_chart_marker default_marker_dot = {.type = LXW_CHART_MARKER_DOT, - .size = 3 - }; + .size = 3}; /* Check if there are any series for this axis type. */ STAILQ_FOREACH(series, self->series_list, list_pointers) { @@ -5881,10 +5878,8 @@ _chart_write_scatter_plot_area(lxw_chart *self) } /* Write the c:spPr element for the plotarea formatting. */ - _chart_write_sp_pr_with_gradient(self, self->plotarea_line, - self->plotarea_fill, - self->plotarea_pattern, - self->plotarea_gradient); + _chart_write_sp_pr_with_gradient(self, self->plotarea_line, self->plotarea_fill, + self->plotarea_pattern, self->plotarea_gradient); lxw_xml_end_tag(self->file, "c:plotArea"); } @@ -5913,10 +5908,8 @@ _chart_write_pie_plot_area(lxw_chart *self) } /* Write the c:spPr element for the plotarea formatting. */ - _chart_write_sp_pr_with_gradient(self, self->plotarea_line, - self->plotarea_fill, - self->plotarea_pattern, - self->plotarea_gradient); + _chart_write_sp_pr_with_gradient(self, self->plotarea_line, self->plotarea_fill, + self->plotarea_pattern, self->plotarea_gradient); lxw_xml_end_tag(self->file, "c:plotArea"); } @@ -5986,10 +5979,8 @@ _chart_write_stock_plot_area(lxw_chart *self) _chart_write_d_table(self); /* Write the c:spPr element for the plotarea formatting. */ - _chart_write_sp_pr_with_gradient(self, self->plotarea_line, - self->plotarea_fill, - self->plotarea_pattern, - self->plotarea_gradient); + _chart_write_sp_pr_with_gradient(self, self->plotarea_line, self->plotarea_fill, + self->plotarea_pattern, self->plotarea_gradient); lxw_xml_end_tag(self->file, "c:plotArea"); } @@ -6072,10 +6063,8 @@ _chart_write_plot_area(lxw_chart *self) _chart_write_d_table(self); /* Write the c:spPr element for the plotarea formatting. */ - _chart_write_sp_pr_with_gradient(self, self->plotarea_line, - self->plotarea_fill, - self->plotarea_pattern, - self->plotarea_gradient); + _chart_write_sp_pr_with_gradient(self, self->plotarea_line, self->plotarea_fill, + self->plotarea_pattern, self->plotarea_gradient); lxw_xml_end_tag(self->file, "c:plotArea"); } @@ -6435,10 +6424,8 @@ lxw_chart_assemble_xml_file(lxw_chart *self) _chart_write_chart(self); /* Write the c:spPr element for the chartarea formatting. */ - _chart_write_sp_pr_with_gradient(self, self->chartarea_line, - self->chartarea_fill, - self->chartarea_pattern, - self->chartarea_gradient); + _chart_write_sp_pr_with_gradient(self, self->chartarea_line, self->chartarea_fill, + self->chartarea_pattern, self->chartarea_gradient); /* Write the c:printSettings element. */ if (!self->is_chartsheet) @@ -6481,14 +6468,15 @@ lxw_chart_add_data_cache(lxw_series_range *range, uint8_t *data, * Add a series to the chart. */ lxw_chart_series * -chart_add_series_impl(lxw_chart *self, const char *categories, - const char *values, uint8_t y2_axis) +chart_add_series_impl(lxw_chart *self, const char *categories, const char *values, + uint8_t y2_axis) { lxw_chart_series *series; /* Scatter charts require categories and values. */ if (self->chart_group == LXW_CHART_SCATTER && values && !categories) { - LXW_WARN("chart_add_series(): scatter charts must have " "'categories' and 'values'"); /* Keep user-facing name */ + LXW_WARN("chart_add_series(): scatter charts must have " + "'categories' and 'values'"); /* Keep user-facing name */ return NULL; } @@ -7964,8 +7952,7 @@ chart_chartarea_set_pattern(lxw_chart *self, lxw_chart_pattern *pattern) * Set a gradient fill type for the chartarea. */ void -chart_chartarea_set_gradient(lxw_chart *self, - lxw_chart_gradient_fill *gradient) +chart_chartarea_set_gradient(lxw_chart *self, lxw_chart_gradient_fill *gradient) { if (!gradient) return; @@ -8025,8 +8012,7 @@ chart_plotarea_set_pattern(lxw_chart *self, lxw_chart_pattern *pattern) * Set a gradient fill type for the plotarea. */ void -chart_plotarea_set_gradient(lxw_chart *self, - lxw_chart_gradient_fill *gradient) +chart_plotarea_set_gradient(lxw_chart *self, lxw_chart_gradient_fill *gradient) { if (!gradient) return; @@ -8207,9 +8193,9 @@ chart_set_series_overlap_y2(lxw_chart *self, int8_t overlap) if (overlap >= -100 && overlap <= 100) self->overlap_y2 = overlap; else - LXW_WARN_FORMAT1 - ("chart_set_series_overlap_y2(): Chart series overlap " - "'%d' outside Excel range: -100 <= overlap <= 100", overlap); + LXW_WARN_FORMAT1("chart_set_series_overlap_y2(): Chart series overlap " + "'%d' outside Excel range: -100 <= overlap <= 100", + overlap); } /* diff --git a/src/drawing.c b/src/drawing.c index 061e6190..952b9c01 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -664,8 +664,7 @@ _drawing_write_a_prst_geom_rect(lxw_drawing *self) * Write the element for shapes. */ STATIC void -_drawing_write_sp_pr_shape(lxw_drawing *self, - lxw_drawing_object *drawing_object) +_drawing_write_sp_pr_shape(lxw_drawing *self, lxw_drawing_object *drawing_object) { struct xml_attribute_list attributes; struct xml_attribute *attribute; diff --git a/src/feature_property_bag.c b/src/feature_property_bag.c index 5a70e5ec..96dd3825 100644 --- a/src/feature_property_bag.c +++ b/src/feature_property_bag.c @@ -78,7 +78,7 @@ _write_feature_property_bags(lxw_feature_property_bag *self) LXW_INIT_ATTRIBUTES(); LXW_PUSH_ATTRIBUTES_STR("xmlns", - "http://schemas.microsoft.com/office/spreadsheetml/2022/featurepropertybag"); + "http://schemas.microsoft.com/office/spreadsheetml/2022/featurepropertybag"); lxw_xml_start_tag(self->file, "FeaturePropertyBags", &attributes); diff --git a/src/format.c b/src/format.c index dea02ac0..d379bcae 100644 --- a/src/format.c +++ b/src/format.c @@ -548,6 +548,12 @@ format_set_text_justlast(lxw_format *self) void format_set_pattern(lxw_format *self, uint8_t value) { + if (value > LXW_PATTERN_GRAY_0625) { + LXW_WARN_FORMAT1("format_set_pattern(): invalid pattern value: %d", + value); + return; + } + self->pattern = value; } @@ -691,6 +697,12 @@ format_set_diag_color(lxw_format *self, lxw_color_t color) void format_set_diag_border(lxw_format *self, uint8_t style) { + if (style > LXW_BORDER_SLANT_DASH_DOT) { + LXW_WARN_FORMAT1("format_set_diag_border(): invalid border style: %d", + style); + return; + } + self->diag_border = style; } @@ -709,6 +721,13 @@ format_set_num_format_index(lxw_format *self, uint8_t value) void format_set_valign(lxw_format *self, uint8_t value) { + if (value > LXW_ALIGN_VERTICAL_DISTRIBUTED) { + LXW_WARN_FORMAT1 + ("format_set_valign(): invalid vertical alignment value: %d", + value); + return; + } + self->text_v_align = value; } diff --git a/src/labview_wrappers.c b/src/labview_wrappers.c index cb47538d..91c8e725 100644 --- a/src/labview_wrappers.c +++ b/src/labview_wrappers.c @@ -36,7 +36,7 @@ ansi_to_utf8(const char *ansi_str) if (wide_len == 0) return NULL; - wchar_t *wide_str = (wchar_t *) malloc(wide_len * sizeof(wchar_t)); + wchar_t *wide_str = (wchar_t *)malloc(wide_len * sizeof(wchar_t)); if (!wide_str) return NULL; @@ -46,21 +46,19 @@ ansi_to_utf8(const char *ansi_str) } /* Then convert UTF-16 to UTF-8 */ - int utf8_len = - WideCharToMultiByte(CP_UTF8, 0, wide_str, -1, NULL, 0, NULL, NULL); + 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); + 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) { + if (WideCharToMultiByte(CP_UTF8, 0, wide_str, -1, utf8_str, utf8_len, NULL, NULL) == 0) { free(wide_str); free(utf8_str); return NULL; @@ -89,27 +87,21 @@ ansi_to_utf8(const char *str) * ============================================================================ */ lxw_error -worksheet_write_string_lv(lxw_worksheet *worksheet, lxw_row_t row, - lxw_col_t col, const char *string, - lxw_format *format) +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); + 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) +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); + lxw_error err = worksheet_write_formula(worksheet, row, col, utf8 ? utf8 : formula, format); free(utf8); return err; } @@ -119,19 +111,17 @@ 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); + 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) +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); + lxw_error err = worksheet_write_comment(worksheet, row, col, utf8 ? utf8 : string); free(utf8); return err; } @@ -155,16 +145,13 @@ worksheet_set_footer_lv(lxw_worksheet *worksheet, const char *footer) } 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, +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); + lxw_error err = worksheet_merge_range(worksheet, first_row, first_col, last_row, last_col, + utf8 ? utf8 : string, format); free(utf8); return err; } @@ -178,25 +165,21 @@ worksheet_set_comments_author_lv(lxw_worksheet *worksheet, const char *author) } lxw_error -worksheet_insert_textbox_lv(lxw_worksheet *worksheet, lxw_row_t row, - lxw_col_t col, const char *text) +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); + 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) +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); + lxw_error err = worksheet_insert_textbox_opt(worksheet, row, col, utf8 ? utf8 : text, options); free(utf8); return err; } @@ -206,17 +189,15 @@ worksheet_insert_textbox_opt_lv(lxw_worksheet *worksheet, lxw_row_t row, * ============================================================================ */ lxw_chart_series * -chart_add_series_lv(lxw_chart *chart, const char *categories, - const char *values, uint8_t y2_axis) +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); + utf8_cat ? utf8_cat : categories, + utf8_val ? utf8_val : values, + y2_axis); free(utf8_cat); free(utf8_val); return series; @@ -263,8 +244,7 @@ chart_axis_set_num_format_lv(lxw_chart_axis *axis, const char *num_format) } void -chart_series_set_labels_num_format_lv(lxw_chart_series *series, - const char *num_format) +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); @@ -272,10 +252,9 @@ chart_series_set_labels_num_format_lv(lxw_chart_series *series, } 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) +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, @@ -295,9 +274,8 @@ chart_series_set_values_lv(lxw_chart_series *series, const char *sheetname, } void -chart_series_set_name_range_lv(lxw_chart_series *series, - const char *sheetname, lxw_row_t row, - lxw_col_t col) +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); @@ -354,8 +332,7 @@ workbook_add_worksheet_lv(lxw_workbook *workbook, const char *sheetname) return workbook_add_worksheet(workbook, NULL); } char *utf8 = ansi_to_utf8(sheetname); - lxw_worksheet *ws = - workbook_add_worksheet(workbook, utf8 ? utf8 : sheetname); + lxw_worksheet *ws = workbook_add_worksheet(workbook, utf8 ? utf8 : sheetname); free(utf8); return ws; } @@ -368,22 +345,19 @@ workbook_add_chartsheet_lv(lxw_workbook *workbook, const char *sheetname) return workbook_add_chartsheet(workbook, NULL); } char *utf8 = ansi_to_utf8(sheetname); - lxw_chartsheet *cs = - workbook_add_chartsheet(workbook, utf8 ? 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) +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); + utf8_formula ? utf8_formula : formula); free(utf8_name); free(utf8_formula); return err; @@ -393,8 +367,7 @@ 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); + lxw_worksheet *ws = workbook_get_worksheet_by_name(workbook, utf8 ? utf8 : name); free(utf8); return ws; } @@ -403,8 +376,7 @@ 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); + lxw_chartsheet *cs = workbook_get_chartsheet_by_name(workbook, utf8 ? utf8 : name); free(utf8); return cs; } @@ -413,23 +385,20 @@ 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); + 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) +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); + utf8_name ? utf8_name : name, + utf8_value ? utf8_value : value); free(utf8_name); free(utf8_value); return err; @@ -480,49 +449,41 @@ workbook_new_opt_lv(const char *filename, lxw_workbook_options *options) } lxw_error -worksheet_insert_image_lv(lxw_worksheet *worksheet, lxw_row_t row, - lxw_col_t col, const char *filename) +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); + 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) +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); + 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) +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); + 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) +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); + lxw_error err = worksheet_embed_image_opt(worksheet, row, col, utf8 ? utf8 : filename, options); free(utf8); return err; } @@ -531,8 +492,7 @@ 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); + lxw_error err = worksheet_set_background(worksheet, utf8 ? utf8 : filename); free(utf8); return err; } @@ -541,24 +501,20 @@ 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); + 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, +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); + utf8_vba ? utf8_vba : vba_project, + utf8_sig ? utf8_sig : signature); free(utf8_vba); free(utf8_sig); return err; @@ -570,10 +526,9 @@ workbook_add_signed_vba_project_lv(lxw_workbook *workbook, lxw_error worksheet_filter_column_lv(lxw_worksheet *worksheet, lxw_col_t col, - uint8_t criteria, const char *value_string, - double value) + uint8_t criteria, const char *value_string, double value) { - lxw_filter_rule rule = { 0 }; + lxw_filter_rule rule = {0}; rule.criteria = criteria; rule.value = value; @@ -592,13 +547,12 @@ worksheet_filter_column_lv(lxw_worksheet *worksheet, lxw_col_t col, 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 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 }; + lxw_filter_rule rule1 = {0}; + lxw_filter_rule rule2 = {0}; char *utf8_1 = NULL; char *utf8_2 = NULL; @@ -617,8 +571,7 @@ worksheet_filter_column2_lv(lxw_worksheet *worksheet, lxw_col_t col, rule2.value_string = utf8_2 ? utf8_2 : value_string2; } - lxw_error err = - worksheet_filter_column2(worksheet, col, &rule1, &rule2, and_or); + lxw_error err = worksheet_filter_column2(worksheet, col, &rule1, &rule2, and_or); free(utf8_1); free(utf8_2); @@ -632,7 +585,8 @@ worksheet_filter_column2_lv(lxw_worksheet *worksheet, lxw_col_t col, lxw_error chart_series_set_labels_custom_lv(lxw_chart_series *series, uintptr_t *values, - uint8_t *hide_flags, uint16_t count) + uint8_t *hide_flags, + uint16_t count) { lxw_error err = LXW_NO_ERROR; uint16_t i; @@ -644,12 +598,9 @@ chart_series_set_labels_custom_lv(lxw_chart_series *series, 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 *)); + 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); @@ -666,7 +617,7 @@ chart_series_set_labels_custom_lv(lxw_chart_series *series, label_ptrs[i] = &labels[i]; /* Get string pointer from uintptr_t array */ - str = (values && values[i]) ? (const char *) values[i] : NULL; + str = (values && values[i]) ? (const char *)values[i] : NULL; /* Convert value string if provided */ if (str && str[0]) { diff --git a/src/styles.c b/src/styles.c index 4fe04252..e4c96333 100644 --- a/src/styles.c +++ b/src/styles.c @@ -1201,7 +1201,7 @@ _write_xf_format_extensions(lxw_styles *self) 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"); + "http://schemas.microsoft.com/office/spreadsheetml/2022/featurepropertybag"); lxw_xml_start_tag(self->file, "ext", &attributes); LXW_FREE_ATTRIBUTES(); diff --git a/src/utility.c b/src/utility.c index a88425a5..d3926176 100644 --- a/src/utility.c +++ b/src/utility.c @@ -41,6 +41,7 @@ char *error_strings[LXW_MAX_ERRNO + 1] = { "NULL function parameter ignored.", "Function parameter validation error.", "Function string parameter is empty.", + "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.", @@ -332,6 +333,72 @@ lxw_name_to_col_2(const char *col_str) return 0; } +/* + * Validate a lxw_datetime struct. + */ +lxw_error +lxw_datetime_validate(lxw_datetime *datetime) +{ + if (!datetime) + return LXW_ERROR_DATETIME_VALIDATION; + + /* + * Excel uses the year 1900 as the default epoch but it uses 1899-12-31 as + * the 0 date and internally we use the 0-0-0 date for time only values. + */ + if (datetime->year < 1900 && + !(datetime->year == 0 && + datetime->month == 0 && datetime->day == 0) && + !(datetime->year == 1899 && + datetime->month == 12 && datetime->day == 31)) { + + LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid year: %d. " + "Valid range is 1900-9999.", datetime->year); + + return LXW_ERROR_DATETIME_VALIDATION; + } + + if (datetime->year > 9999) { + LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid year: %d. " + "Valid range is 1900-9999.", datetime->year); + return LXW_ERROR_DATETIME_VALIDATION; + } + + if (datetime->year != 0) { + if (datetime->month < 1 || datetime->month > 12) { + LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid month: %d. " + "Valid range is 1-12.", datetime->month); + return LXW_ERROR_DATETIME_VALIDATION; + } + + if (datetime->day < 1 || datetime->day > 31) { + LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid day: %d. " + "Valid range is 1-31.", datetime->day); + return LXW_ERROR_DATETIME_VALIDATION; + } + } + + if (datetime->hour < 0 || datetime->hour > 23) { + LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid hour: %d. " + "Valid range is 0-23.", datetime->hour); + return LXW_ERROR_DATETIME_VALIDATION; + } + + if (datetime->min < 0 || datetime->min > 59) { + LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid minute: %d. " + "Valid range is 0-59.", datetime->min); + return LXW_ERROR_DATETIME_VALIDATION; + } + + if (datetime->sec < 0.0 || datetime->sec >= 60.0) { + LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid seconds: %.3f. " + "Valid range is 0.0-59.999.", datetime->sec); + return LXW_ERROR_DATETIME_VALIDATION; + } + + return LXW_NO_ERROR; +} + /* * Convert a lxw_datetime struct to an Excel serial date, with a 1900 * or 1904 epoch. @@ -357,6 +424,9 @@ lxw_datetime_to_excel_date_with_epoch(lxw_datetime *datetime, int days = 0; int i; + if (lxw_datetime_validate(datetime) != LXW_NO_ERROR) + return 0.0; + /* For times without dates set the default date for the epoch. */ if (!year) { if (!use_1904_epoch) { @@ -688,101 +758,101 @@ lxw_hash_password(const char *password) * 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 /* ~ */ + 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 /* ~ */ }; /* @@ -819,7 +889,7 @@ lxw_autofit_width(const char *string) { uint16_t pixels; double width; - const double max_digit_width = 7.0; /* For Calibri 11 */ + const double max_digit_width = 7.0; /* For Calibri 11 */ const double padding = 5.0; if (string == NULL || *string == '\0') diff --git a/src/workbook.c b/src/workbook.c index 3caf0fad..754e2a73 100644 --- a/src/workbook.c +++ b/src/workbook.c @@ -1272,8 +1272,7 @@ _prepare_drawings(lxw_workbook *self) /* Prepare worksheet textboxes. */ STAILQ_FOREACH(object_props, worksheet->textbox_data, list_pointers) { - lxw_worksheet_prepare_textbox(worksheet, drawing_id, - object_props); + lxw_worksheet_prepare_textbox(worksheet, drawing_id, object_props); } /* Prepare worksheet header/footer images. */ @@ -2207,6 +2206,12 @@ workbook_add_chart(lxw_workbook *self, uint8_t type) { lxw_chart *chart; + if (type == LXW_CHART_NONE || type > LXW_CHART_STOCK) { + LXW_WARN_FORMAT1("workbook_add_chart(): invalid chart type: %d", + type); + return NULL; + } + /* Create a new chart object. */ chart = lxw_chart_new(type); @@ -2697,6 +2702,10 @@ workbook_set_custom_property_datetime(lxw_workbook *self, const char *name, return LXW_ERROR_NULL_PARAMETER_IGNORED; } + if (lxw_datetime_validate(datetime) != LXW_NO_ERROR) { + return LXW_ERROR_DATETIME_VALIDATION; + } + /* Create a struct to hold the custom property. */ custom_property = calloc(1, sizeof(struct lxw_custom_property)); RETURN_ON_MEM_ERROR(custom_property, LXW_ERROR_MEMORY_MALLOC_FAILED); diff --git a/src/worksheet.c b/src/worksheet.c index f3ce0617..8c7b1a40 100644 --- a/src/worksheet.c +++ b/src/worksheet.c @@ -7293,8 +7293,7 @@ _worksheet_write_sparkline_color(lxw_worksheet *self, const char *tag, * Write the element. */ STATIC void -_worksheet_write_sparkline_group(lxw_worksheet *self, - lxw_sparkline *sparkline) +_worksheet_write_sparkline_group(lxw_worksheet *self, lxw_sparkline *sparkline) { struct xml_attribute_list attributes; struct xml_attribute *attribute; @@ -8647,7 +8646,8 @@ worksheet_write_boolean(lxw_worksheet *self, */ lxw_error worksheet_insert_checkbox(lxw_worksheet *self, - lxw_row_t row_num, lxw_col_t col_num, int value) + lxw_row_t row_num, lxw_col_t col_num, + int value) { lxw_cell *cell; lxw_error err; @@ -9917,8 +9917,7 @@ worksheet_add_sparkline(lxw_worksheet *self, lxw_row_t row, lxw_col_t col, char location[LXW_MAX_CELL_NAME_LENGTH]; if (!user_options) { - LXW_WARN - ("worksheet_add_sparkline(): options parameter cannot be NULL"); + LXW_WARN("worksheet_add_sparkline(): options parameter cannot be NULL"); return LXW_ERROR_NULL_PARAMETER_IGNORED; } @@ -9985,7 +9984,7 @@ worksheet_add_sparkline(lxw_worksheet *self, lxw_row_t row, lxw_col_t col, sparkline->weight = user_options->weight; if (sparkline->weight == 0.0) - sparkline->weight = 0.75; /* Default line weight */ + sparkline->weight = 0.75; /* Default line weight */ if (user_options->date_axis) { sparkline->date_axis = lxw_strdup(user_options->date_axis);