Skip to content

Commit b0eb611

Browse files
authored
Merge pull request #5 from jaakkor2/upd
Add two tests: autofilter and chart_data_tools. Fix lxw_chart_point.
2 parents 0166fa2 + e1745f4 commit b0eb611

File tree

6 files changed

+536
-6
lines changed

6 files changed

+536
-6
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "LibXLSXWriter"
22
uuid = "d9c5391f-cdb8-42e0-9032-91a2542ec5a4"
33
authors = ["Jaakko Ruohio [email protected]"]
4-
version = "0.1.1"
4+
version = "0.1.2"
55

66
[deps]
77
CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82"

src/LibXLSXWriter.jl

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,25 @@ using Printf
66

77
include("generated/libxlsxwriter_api.jl")
88

9-
lxw_chart_fill(; color=0x0, none=0x0, transparency=0x0) = lxw_chart_fill(color, none, transparency)
10-
lxw_chart_line(; color=0x0, none=0x0, width=0.0, dash_type=0x0, transparency=0x0) = lxw_chart_line(color, none, width, dash_type, transparency)
11-
lxw_chart_pattern(; fg_color=0x0, bg_color=0x0, type=0x0) = lxw_chart_pattern(fg_color, bg_color, type)
12-
lxw_chart_point(; line=lxw_chart_line(), fill=lxw_chart_fill(), pattern=lxw_chart_pattern()) = lxw_chart_point(Ptr{line}(), Ptr{fill}(), Ptr{pattern}())
9+
lxw_chart_fill(; color=0x0, none=0x0, transparency=0x0) = Ref(lxw_chart_fill(color, none, transparency))
10+
lxw_chart_line(; color=0x0, none=0x0, width=0.0, dash_type=0x0, transparency=0x0) = Ref(lxw_chart_line(color, none, width, dash_type, transparency))
11+
lxw_chart_pattern(; fg_color=0x0, bg_color=0x0, type=LXW_PATTERN_NONE) = Ref(lxw_chart_pattern(fg_color, bg_color, type))
12+
13+
function lxw_chart_point(; line=C_NULL, fill=C_NULL, pattern=C_NULL)
14+
Ref(lxw_chart_point(
15+
Base.unsafe_convert(Ptr{lxw_chart_line}, line),
16+
Base.unsafe_convert(Ptr{lxw_chart_fill}, fill),
17+
Base.unsafe_convert(Ptr{lxw_chart_pattern}, pattern)
18+
))
19+
end
1320

1421
Cs(mystring) = Base.unsafe_convert(Cstring, mystring)
1522
lxw_doc_properties(; title="", subject="", author="", manager="", company="", category="", keywords="", comments="", status="", hyperlink_base="", created=0) =
1623
Ref(lxw_doc_properties(Cs(title), Cs(subject), Cs(author), Cs(manager), Cs(company), Cs(category), Cs(keywords), Cs(comments), Cs(status), Cs(hyperlink_base), created))
1724

25+
lxw_row_col_options(; hidden=0x0, level=0x0, collapsed=0x0) = Ref(lxw_row_col_options(hidden, level, collapsed))
26+
lxw_filter_rule(; criteria=0x0, value_string="", value=0.0) = Ref(lxw_filter_rule(criteria, Cs(value_string), value))
27+
1828
# utility.h
1929
CELL(cell) = lxw_name_to_row(cell), lxw_name_to_col(cell)
2030
COLS(cols) = lxw_name_to_col(cols), lxw_name_to_col_2(cols)

test/autofilter.jl

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
#=
2+
https://github.com/jmcnamara/libxlsxwriter/blob/main/examples/autofilter.c
3+
/*
4+
* Example of adding an autofilter to a worksheet in Excel using
5+
* libxlsxwriter.
6+
*
7+
* Copyright 2014-2025, John McNamara, [email protected]
8+
*/
9+
=#
10+
11+
using LibXLSXWriter: lxw_worksheet, lxw_format, worksheet_set_column, worksheet_set_row, worksheet_write_string, workbook_new, workbook_add_worksheet, lxw_row_col_options, LXW_TRUE, workbook_add_format, format_set_bold, worksheet_write_number, worksheet_autofilter, worksheet_set_row_opt, LXW_DEF_ROW_HEIGHT, lxw_filter_rule, worksheet_filter_column, worksheet_filter_column2, worksheet_filter_list, workbook_close
12+
using LibXLSXWriter: LXW_FILTER_CRITERIA_EQUAL_TO, LXW_FILTER_CRITERIA_GREATER_THAN, LXW_FILTER_CRITERIA_LESS_THAN, LXW_FILTER_AND, LXW_FILTER_OR, LXW_FILTER_CRITERIA_BLANKS, LXW_FILTER_CRITERIA_NON_BLANKS
13+
14+
function write_worksheet_header(worksheet::Ptr{lxw_worksheet}, header::Ptr{lxw_format})
15+
16+
# Make the columns wider for clarity.
17+
worksheet_set_column(worksheet, 0, 3, 12, C_NULL)
18+
19+
20+
# Write the column headers.
21+
worksheet_set_row(worksheet, 0, 20, header)
22+
worksheet_write_string(worksheet, 0, 0, "Region", C_NULL)
23+
worksheet_write_string(worksheet, 0, 1, "Item", C_NULL)
24+
worksheet_write_string(worksheet, 0, 2, "Volume", C_NULL)
25+
worksheet_write_string(worksheet, 0, 3, "Month", C_NULL)
26+
nothing
27+
end
28+
29+
workbook = workbook_new("autofilter.xlsx")
30+
worksheet1 = workbook_add_worksheet(workbook, C_NULL)
31+
worksheet2 = workbook_add_worksheet(workbook, C_NULL)
32+
worksheet3 = workbook_add_worksheet(workbook, C_NULL)
33+
worksheet4 = workbook_add_worksheet(workbook, C_NULL)
34+
worksheet5 = workbook_add_worksheet(workbook, C_NULL)
35+
worksheet6 = workbook_add_worksheet(workbook, C_NULL)
36+
worksheet7 = workbook_add_worksheet(workbook, C_NULL)
37+
38+
mutable struct row
39+
region::String
40+
item::String
41+
volume::Int
42+
month::String
43+
end
44+
45+
data = [
46+
("East", "Apple", 9000, "July" ),
47+
("East", "Apple", 5000, "July" ),
48+
("South", "Orange", 9000, "September" ),
49+
("North", "Apple", 2000, "November" ),
50+
("West", "Apple", 9000, "November" ),
51+
("South", "Pear", 7000, "October" ),
52+
("North", "Pear", 9000, "August" ),
53+
("West", "Orange", 1000, "December" ),
54+
("West", "Grape", 1000, "November" ),
55+
("South", "Pear", 10000, "April" ),
56+
("West", "Grape", 6000, "January" ),
57+
("South", "Orange", 3000, "May" ),
58+
("North", "Apple", 3000, "December" ),
59+
("South", "Apple", 7000, "February" ),
60+
("West", "Grape", 1000, "December" ),
61+
("East", "Grape", 8000, "February" ),
62+
("South", "Grape", 10000, "June" ),
63+
("West", "Pear", 7000, "December" ),
64+
("South", "Apple", 2000, "October" ),
65+
("East", "Grape", 7000, "December" ),
66+
("North", "Grape", 6000, "April" ),
67+
("East", "Pear", 8000, "February" ),
68+
("North", "Apple", 7000, "August" ),
69+
("North", "Orange", 7000, "July" ),
70+
("North", "Apple", 6000, "June" ),
71+
("South", "Grape", 8000, "September" ),
72+
("West", "Apple", 3000, "October" ),
73+
("South", "Orange", 10000, "November" ),
74+
("West", "Grape", 4000, "July" ),
75+
("North", "Orange", 5000, "August" ),
76+
("East", "Orange", 1000, "November" ),
77+
("East", "Orange", 4000, "October" ),
78+
("North", "Grape", 5000, "August" ),
79+
("East", "Apple", 1000, "December" ),
80+
("South", "Apple", 10000, "March" ),
81+
("East", "Grape", 7000, "October" ),
82+
("West", "Grape", 1000, "September" ),
83+
("East", "Grape", 10000, "October" ),
84+
("South", "Orange", 8000, "March" ),
85+
("North", "Apple", 4000, "July" ),
86+
("South", "Orange", 5000, "July" ),
87+
("West", "Apple", 4000, "June" ),
88+
("East", "Apple", 5000, "April" ),
89+
("North", "Pear", 3000, "August" ),
90+
("East", "Grape", 9000, "November" ),
91+
("North", "Orange", 8000, "October" ),
92+
("East", "Apple", 10000, "June" ),
93+
("South", "Pear", 1000, "December" ),
94+
("North", "Grape", 10000, "July" ),
95+
("East", "Grape", 6000, "February" )
96+
]
97+
98+
data = [row(x...) for x in data]
99+
100+
hidden = lxw_row_col_options(hidden = LXW_TRUE)
101+
102+
header = workbook_add_format(workbook)
103+
format_set_bold(header)
104+
105+
## Example 1. Autofilter without conditions.
106+
107+
# Set up the worksheet data.
108+
write_worksheet_header(worksheet1, header)
109+
110+
# Write the row data.
111+
for i in 1:length(data)
112+
worksheet_write_string(worksheet1, i, 0, data[i].region, C_NULL)
113+
worksheet_write_string(worksheet1, i, 1, data[i].item, C_NULL)
114+
worksheet_write_number(worksheet1, i, 2, data[i].volume, C_NULL)
115+
worksheet_write_string(worksheet1, i, 3, data[i].month, C_NULL)
116+
end
117+
118+
119+
# Add the autofilter.
120+
worksheet_autofilter(worksheet1, 0, 0, 50, 3)
121+
122+
123+
## Example 2. Autofilter with a filter condition in the first column.
124+
125+
# Set up the worksheet data.
126+
write_worksheet_header(worksheet2, header)
127+
128+
# Write the row data.
129+
for i in 1:length(data)
130+
worksheet_write_string(worksheet2, i, 0, data[i].region, C_NULL)
131+
worksheet_write_string(worksheet2, i, 1, data[i].item, C_NULL)
132+
worksheet_write_number(worksheet2, i, 2, data[i].volume, C_NULL)
133+
worksheet_write_string(worksheet2, i, 3, data[i].month, C_NULL)
134+
135+
# It isn't sufficient to just apply the filter condition below. We
136+
# must also hide the rows that don't match the criteria since Excel
137+
# doesn't do that automatically.
138+
if data[i].region == "East"
139+
# Row matches the filter, no further action required.
140+
else
141+
# Hide rows that don't match the filter.
142+
worksheet_set_row_opt(worksheet2, i, LXW_DEF_ROW_HEIGHT, C_NULL, hidden)
143+
end
144+
145+
#=
146+
Note, the if() statement above is written to match the logic of the
147+
criteria in worksheet_filter_column() below. However you could get
148+
the same results with the following simpler, but reversed, code:
149+
150+
if data[i].region != "East")
151+
worksheet_set_row_opt(worksheet2, i + 1, LXW_DEF_ROW_HEIGHT, C_NULL, &hidden)
152+
end
153+
154+
The same applies to the Examples 3-6 as well.
155+
=#
156+
end
157+
158+
159+
# Add the autofilter.
160+
worksheet_autofilter(worksheet2, 0, 0, 50, 3)
161+
162+
# Add the filter criteria.
163+
164+
filter_rule2 = lxw_filter_rule(criteria = LXW_FILTER_CRITERIA_EQUAL_TO, value_string = "East")
165+
166+
worksheet_filter_column(worksheet2, 0, filter_rule2)
167+
168+
169+
## Example 3. Autofilter with a dual filter condition in one of the columns.
170+
171+
# Set up the worksheet data.
172+
write_worksheet_header(worksheet3, header)
173+
174+
# Write the row data.
175+
for i in 1:length(data)
176+
worksheet_write_string(worksheet3, i, 0, data[i].region, C_NULL)
177+
worksheet_write_string(worksheet3, i, 1, data[i].item, C_NULL)
178+
worksheet_write_number(worksheet3, i, 2, data[i].volume, C_NULL)
179+
worksheet_write_string(worksheet3, i, 3, data[i].month, C_NULL)
180+
181+
if data[i].region == "East" || data[i].region == "South"
182+
# Row matches the filter, no further action required.
183+
else
184+
# We need to hide rows that don't match the filter.
185+
worksheet_set_row_opt(worksheet3, i, LXW_DEF_ROW_HEIGHT, C_NULL, hidden)
186+
end
187+
end
188+
189+
# Add the autofilter.
190+
worksheet_autofilter(worksheet3, 0, 0, 50, 3)
191+
192+
# Add the filter criteria.
193+
filter_rule3a = lxw_filter_rule(criteria = LXW_FILTER_CRITERIA_EQUAL_TO, value_string = "East")
194+
195+
filter_rule3b = lxw_filter_rule(criteria = LXW_FILTER_CRITERIA_EQUAL_TO, value_string = "South")
196+
197+
worksheet_filter_column2(worksheet3, 0, filter_rule3a, filter_rule3b, LXW_FILTER_OR)
198+
199+
200+
201+
## Example 4. Autofilter with filter conditions in two columns.
202+
203+
# Set up the worksheet data.
204+
write_worksheet_header(worksheet4, header)
205+
206+
# Write the row data.
207+
for i in 1:length(data)
208+
worksheet_write_string(worksheet4, i, 0, data[i].region, C_NULL)
209+
worksheet_write_string(worksheet4, i, 1, data[i].item, C_NULL)
210+
worksheet_write_number(worksheet4, i, 2, data[i].volume, C_NULL)
211+
worksheet_write_string(worksheet4, i, 3, data[i].month, C_NULL)
212+
213+
if data[i].region == "East" && data[i].volume > 3000 && data[i].volume < 8000
214+
# Row matches the filter, no further action required.
215+
else
216+
# We need to hide rows that don't match the filter.
217+
worksheet_set_row_opt(worksheet4, i, LXW_DEF_ROW_HEIGHT, C_NULL, hidden)
218+
end
219+
end
220+
221+
# Add the autofilter.
222+
worksheet_autofilter(worksheet4, 0, 0, 50, 3)
223+
224+
# Add the filter criteria.
225+
filter_rule4a = lxw_filter_rule(criteria = LXW_FILTER_CRITERIA_EQUAL_TO, value_string = "East")
226+
227+
filter_rule4b = lxw_filter_rule(criteria = LXW_FILTER_CRITERIA_GREATER_THAN, value = 3000)
228+
229+
filter_rule4c = lxw_filter_rule(criteria = LXW_FILTER_CRITERIA_LESS_THAN, value = 8000)
230+
231+
worksheet_filter_column(worksheet4, 0, filter_rule4a)
232+
worksheet_filter_column2(worksheet4, 2, filter_rule4b, filter_rule4c, LXW_FILTER_AND)
233+
234+
235+
## Example 5. Autofilter with a dual filter condition in one of the columns.
236+
237+
# Set up the worksheet data.
238+
write_worksheet_header(worksheet5, header)
239+
240+
# Write the row data.
241+
for i in 1:length(data)
242+
worksheet_write_string(worksheet5, i, 0, data[i].region, C_NULL)
243+
worksheet_write_string(worksheet5, i, 1, data[i].item, C_NULL)
244+
worksheet_write_number(worksheet5, i, 2, data[i].volume, C_NULL)
245+
worksheet_write_string(worksheet5, i, 3, data[i].month, C_NULL)
246+
247+
if data[i].region == "East" || data[i].region == "North" || data[i].region == "South"
248+
# Row matches the filter, no further action required.
249+
else
250+
# We need to hide rows that don't match the filter.
251+
worksheet_set_row_opt(worksheet5, i, LXW_DEF_ROW_HEIGHT, C_NULL, hidden)
252+
end
253+
end
254+
255+
# Add the autofilter.
256+
worksheet_autofilter(worksheet5, 0, 0, 50, 3)
257+
258+
# Add the filter criteria.
259+
list = ["East", "North", "South"]
260+
261+
worksheet_filter_list(worksheet5, 0, list)
262+
263+
264+
## Example 6. Autofilter with filter for blanks.
265+
266+
# Set up the worksheet data.
267+
write_worksheet_header(worksheet6, header)
268+
269+
# Simulate one blank cell in the data, to test the filter.
270+
data[5+1].region = ""
271+
272+
273+
# Write the row data.
274+
for i in 1:length(data)
275+
worksheet_write_string(worksheet6, i, 0, data[i].region, C_NULL)
276+
worksheet_write_string(worksheet6, i, 1, data[i].item, C_NULL)
277+
worksheet_write_number(worksheet6, i, 2, data[i].volume, C_NULL)
278+
worksheet_write_string(worksheet6, i, 3, data[i].month, C_NULL)
279+
280+
if data[i].region == ""
281+
# Row matches the filter, no further action required.
282+
else
283+
# We need to hide rows that don't match the filter.
284+
worksheet_set_row_opt(worksheet6, i, LXW_DEF_ROW_HEIGHT, C_NULL, hidden)
285+
end
286+
end
287+
288+
# Add the autofilter.
289+
worksheet_autofilter(worksheet6, 0, 0, 50, 3)
290+
291+
# Add the filter criteria.
292+
filter_rule6 = lxw_filter_rule(criteria = LXW_FILTER_CRITERIA_BLANKS)
293+
294+
worksheet_filter_column(worksheet6, 0, filter_rule6)
295+
296+
297+
## Example 7. Autofilter with filter for non-blanks.
298+
299+
# Set up the worksheet data.
300+
write_worksheet_header(worksheet7, header)
301+
302+
# Write the row data.
303+
for i in 1:length(data)
304+
worksheet_write_string(worksheet7, i, 0, data[i].region, C_NULL)
305+
worksheet_write_string(worksheet7, i, 1, data[i].item, C_NULL)
306+
worksheet_write_number(worksheet7, i, 2, data[i].volume, C_NULL)
307+
worksheet_write_string(worksheet7, i, 3, data[i].month, C_NULL)
308+
309+
if data[i].region != ""
310+
# Row matches the filter, no further action required.
311+
else
312+
# We need to hide rows that don't match the filter.
313+
worksheet_set_row_opt(worksheet7, i, LXW_DEF_ROW_HEIGHT, C_NULL, hidden)
314+
end
315+
end
316+
317+
# Add the autofilter.
318+
worksheet_autofilter(worksheet7, 0, 0, 50, 3)
319+
320+
# Add the filter criteria.
321+
filter_rule7 = lxw_filter_rule(criteria = LXW_FILTER_CRITERIA_NON_BLANKS)
322+
323+
worksheet_filter_column(worksheet7, 0, filter_rule7)
324+
325+
workbook_close(workbook)

0 commit comments

Comments
 (0)