1 module libxlsxd.worksheet;
2 
3 import libxlsxd.types;
4 import libxlsxd.datetime;
5 import libxlsxd.format;
6 import libxlsxd.chart;
7 
8 import libxlsxd.xlsxwrap;
9 
10 private pure string genWriteOverloads() {
11 	import std.array : empty;
12 	import std.format : format;
13 	string[3][] fun = [
14 			["String", "string", ""],
15 			["String", "string", "Format"],
16 			["Int", "long", ""],
17 			["Int", "long", "Format"],
18 			["Boolean", "bool", ""],
19 			["Boolean", "bool", "Format"],
20 			["Number", "double", ""],
21 			["Number", "double", "Format"],
22 			["Datetime", "Datetime", ""],
23 			["Datetime", "Datetime", "Format"],
24 			["Formula", "string", ""],
25 			["Formula", "string", "Format"],
26 			["Url", "string", ""],
27 			["Url", "string", "Format"],
28 			["RichString", "lxw_rich_string_tuple**", ""],
29 			["RichString", "lxw_rich_string_tuple**", "Format"],
30 		];
31 	string ret;
32 	version(No_Overloads_Or_Templates) {
33 		immutable overloads = false;
34 		ret ~= `void writeBlank(RowType row, ColType col) {
35 		this.writeBlankImpl(row, col, Format(null));
36 	}
37 
38 	void writeBlankFormat(RowType row, ColType col, Format f) {
39 		this.writeBlankImpl(row, col, f);
40 	}
41 `;
42 
43 	} else {
44 		immutable overloads = true;
45 		ret ~= `void writeBlank(RowType row, ColType col) {
46 		this.writeBlankImpl(row, col, Format(null));
47 	}
48 
49 	void writeBlank(RowType row, ColType col, Format f) {
50 		this.writeBlankImpl(row, col, f);
51 	}
52 `;
53 	}
54 
55 	foreach(string[3] f; fun) {
56 		bool addi = !f[2].empty;
57 		ret ~= format("void write%s%s(RowType row, ColType col, %s value%s) {\n",
58 				f[0],
59 				!overloads && addi ? "Format" : "",
60 				f[1], addi ? ", Format f" : ""
61 			);
62 		ret ~= format("\tthis.write%sImpl(row, col, value%s);\n}\n\n",
63 				f[0], addi ? ", f": ", Format(null)"
64 			);
65 	}
66 	return ret;
67 }
68 
69 struct Worksheet {
70 	import std.string : toStringz;
71 	import std.exception : enforce;
72 	lxw_worksheet* handle;
73 
74 	this(lxw_worksheet* handle) @nogc nothrow {
75 		this.handle = handle;
76 	}
77 
78 	mixin(genWriteOverloads());
79 
80 	void write(T)(RowType row, ColType col, T value) {
81 		this.write(row, col, value, Format(null));
82 	}
83 
84 	void write(T)(RowType row, ColType col, T value, Format format) {
85 		import std.traits : isIntegral, isFloatingPoint, isSomeString;
86 		static if((isFloatingPoint!T || isIntegral!T) && !is(T == bool)) {
87 			this.writeNumberImpl(row, col, value, format);
88 		} else static if(isSomeString!T) {
89 			this.writeStringImpl(row, col, value, format);
90 		} else static if(is(T == Datetime)) {
91 			this.writeDatetimeImpl(row, col, value, format);
92 		} else static if(is(T == bool)) {
93 			this.writeBooleanImpl(row, col, value, format);
94 		} else {
95 			static assert(false, "The function 'write' does not support type
96 					'" ~ T.stringof ~ "'");
97 		}
98 	}
99 
100 	size_t writeAndGetWidth(T)(RowType row, ColType col, T value) {
101 		return writeAndGetWidth(row, col, value, Format(null));
102 	}
103 
104 	size_t writeAndGetWidth(T)(RowType row, ColType col, T value,
105 			Format format)
106 	{
107 		import std.traits : isIntegral, isFloatingPoint, isSomeString;
108 		import std.conv : to;
109 		static if((isFloatingPoint!T || isIntegral!T) && !is(T == bool)) {
110 			this.writeNumberImpl(row, col, value, format);
111 			return to!string(value).length;
112 		} else static if(isSomeString!T) {
113 			this.writeStringImpl(row, col, value, format);
114 			return value.length;
115 		} else static if(is(T == bool)) {
116 			this.writeBooleanImpl(row, col, value, format);
117 			return value ? 4 : 5;
118 		} else {
119 			static assert(false, "The function 'writeAndGetWidth' does not "
120 					~ " support type '" ~ T.stringof ~ "'");
121 		}
122 	}
123 
124 	void writeIntImpl(RowType row, ColType col, double num,
125 			Format format)
126 	{
127 		enforce(worksheet_write_number(this.handle, row, col,
128 					num, format.handle) == LXW_NO_ERROR);
129 	}
130 
131 	void writeNumberImpl(RowType row, ColType col, double num,
132 			Format format)
133 	{
134 		enforce(worksheet_write_number(this.handle, row, col,
135 					num, format.handle) == LXW_NO_ERROR);
136 	}
137 
138 	void writeStringImpl(RowType row, ColType col, string str, Format format) {
139 		enforce(worksheet_write_string(this.handle, row, col,
140 					toStringz(str), format.handle) == LXW_NO_ERROR);
141 	}
142 
143 	private void writeFormulaImpl(RowType row, ColType col, string formula,
144 			Format format)
145 	{
146 		enforce(worksheet_write_formula(this.handle, row, col,
147 					toStringz(formula), format.handle) == LXW_NO_ERROR);
148 	}
149 
150 	void writeArrayFormula(RowType firstRow, ColType firstCol,
151 			RowType lastRow, ColType lastCol, string formula)
152 	{
153 		this.writeArrayFormulaImpl(firstRow, firstCol, lastRow, lastCol,
154 				formula, Format(null));
155 	}
156 
157 	version(No_Overloads_Or_Templates) {
158 		void writeArrayFormulaFormat(RowType firstRow, ColType firstCol,
159 				RowType lastRow, ColType lastCol, string formula, Format format)
160 		{
161 			this.writeArrayFormulaImpl(firstRow, firstCol, lastRow, lastCol,
162 					formula, format);
163 		}
164 	} else {
165 		void writeArrayFormula(RowType firstRow, ColType firstCol,
166 				RowType lastRow, ColType lastCol, string formula, Format format)
167 		{
168 			this.writeArrayFormulaImpl(firstRow, firstCol, lastRow, lastCol,
169 					formula, format);
170 		}
171 	}
172 
173 	private void writeArrayFormulaImpl(RowType firstRow, ColType firstCol,
174 			RowType lastRow, ColType lastCol, string formula, Format format)
175 	{
176 		enforce(worksheet_write_array_formula(this.handle, firstRow,
177 					firstCol, lastRow, lastCol, toStringz(formula),
178 					format.handle) == LXW_NO_ERROR);
179 	}
180 
181 	void writeDatetimeImpl(RowType row, ColType col, Datetime datetime,
182 			Format format)
183 	{
184 		enforce(worksheet_write_datetime(this.handle, row, col,
185 					&datetime.handle, format.handle) == LXW_NO_ERROR);
186 	}
187 
188 	void writeUrlImpl(RowType row, ColType col, string url, Format format) {
189 		enforce(worksheet_write_url(this.handle, row, col,
190 					toStringz(url), format.handle) == LXW_NO_ERROR);
191 	}
192 
193 	void writeBooleanImpl(RowType row, ColType col, bool value, Format format) {
194 		enforce(worksheet_write_boolean(this.handle, row, col,
195 					value, format.handle) == LXW_NO_ERROR);
196 	}
197 
198 	void writeBlankImpl(RowType row, ColType col, Format format) {
199 		enforce(worksheet_write_blank(this.handle, row, col,
200 					format.handle) == LXW_NO_ERROR);
201 	}
202 
203 	void writeFormulaNumImpl(RowType row, ColType col, string formula,
204 			double value, Format format)
205 	{
206 		enforce(worksheet_write_formula_num(this.handle, row,
207 					col, toStringz(formula), format.handle, value
208 				)
209 				== LXW_NO_ERROR
210 			);
211 	}
212 
213 	void writeRichStringImpl(RowType row, ColType col,
214 			lxw_rich_string_tuple** rst, Format format)
215 	{
216 		enforce(worksheet_write_rich_string(this.handle, row,
217 					col, rst, format.handle
218 				)
219 				== LXW_NO_ERROR
220 			);
221 	}
222 
223 	void setRow(RowType row, double height) {
224 		this.setRowImpl(row, height, Format(null));
225 	}
226 
227 	version(No_Overloads_Or_Templates) {
228 		void setRowFormat(RowType row, double height, Format f) {
229 			this.setRowImpl(row, height, f);
230 		}
231 	} else {
232 		void setRow(RowType row, double height, Format f) {
233 			this.setRowImpl(row, height, f);
234 		}
235 	}
236 
237 	private void setRowImpl(RowType row, double height, Format format) {
238 		enforce(worksheet_set_row(this.handle, row, height, format.handle)
239 				== LXW_NO_ERROR
240 			);
241 	}
242 
243 	void setRowOpt(RowType row, double height, lxw_row_col_options* options) {
244 		this.setRowOptImpl(row, height, options, Format(null));
245 	}
246 
247 	version(No_Overloads_Or_Templates) {
248 		void setRowOptFormat(RowType row, double height,
249 				lxw_row_col_options* options, Format f)
250 		{
251 			this.setRowOptImpl(row, height, options, f);
252 		}
253 	} else {
254 		void setRowOpt(RowType row, double height,
255 				lxw_row_col_options* options, Format f)
256 		{
257 			this.setRowOptImpl(row, height, options, f);
258 		}
259 	}
260 
261 	private void setRowOptImpl(RowType row, double height,
262 			lxw_row_col_options* options, Format format)
263 	{
264 		enforce(worksheet_set_row_opt(this.handle, row, height,
265 					format.handle, options) == LXW_NO_ERROR);
266 	}
267 
268 	void setColumn(ColType firstCol, ColType lastCol, double width) {
269 		this.setColumnImpl(firstCol, lastCol, width, Format(null));
270 	}
271 
272 	version(No_Overloads_Or_Templates) {
273 		void setColumnFormat(ColType firstCol, ColType lastCol, double width,
274 				Format f)
275 		{
276 			this.setColumnImpl(firstCol, lastCol, width, f);
277 		}
278 	} else {
279 		void setColumn(ColType firstCol, ColType lastCol, double width,
280 				Format f)
281 		{
282 			this.setColumnImpl(firstCol, lastCol, width, f);
283 		}
284 	}
285 
286 	private void setColumnImpl(ColType firstCol, ColType lastCol, double width,
287 			Format format)
288 	{
289 		enforce(worksheet_set_column(this.handle, firstCol, lastCol,
290 					width, format.handle
291 				)
292 				== LXW_NO_ERROR
293 			);
294 	}
295 
296 	void setColumnOpt(ColType firstCol, ColType lastCol, double width,
297 			lxw_row_col_options* options)
298 	{
299 		this.setColumnOptImpl(firstCol, lastCol, width, options, Format(null));
300 	}
301 
302 	version(No_Overloads_Or_Templates) {
303 		void setColumnOptFormat(ColType firstCol, ColType lastCol, double width,
304 				lxw_row_col_options* options, Format f)
305 		{
306 			this.setColumnOptImpl(firstCol, lastCol, width, options, f);
307 		}
308 	} else {
309 		void setColumnOpt(ColType firstCol, ColType lastCol, double width,
310 				lxw_row_col_options* options, Format f)
311 		{
312 			this.setColumnOptImpl(firstCol, lastCol, width, options, f);
313 		}
314 	}
315 
316 	private void setColumnOptImpl(ColType firstCol, ColType lastCol,
317 			double width, lxw_row_col_options* options, Format format)
318 	{
319 		enforce(worksheet_set_column_opt(this.handle, firstCol, lastCol,
320 					width, format.handle, options)
321 				== LXW_NO_ERROR
322 			);
323 	}
324 
325 	void insertImage(RowType row, ColType col, string filename) {
326 		enforce(worksheet_insert_image(this.handle, row, col,
327 					toStringz(filename)
328 				)
329 				== LXW_NO_ERROR
330 			);
331 	}
332 
333 	void insertImageOpt(RowType row, ColType col, string filename,
334 			lxw_image_options* options)
335 	{
336 		enforce(worksheet_insert_image_opt(this.handle, row, col,
337 					toStringz(filename), options
338 				)
339 				== LXW_NO_ERROR
340 			);
341 	}
342 
343 	void insertImageBuffer(RowType row, ColType col, const(ubyte)* buf,
344 			size_t bufSize)
345 	{
346 		enforce(worksheet_insert_image_buffer(this.handle, row,
347 					col, buf, bufSize
348 				)
349 				== LXW_NO_ERROR
350 			);
351 	}
352 
353 	void insertImageBufferOpt(RowType row, ColType col, const(ubyte)* buf,
354 			size_t bufSize, lxw_image_options* options)
355 	{
356 		enforce(worksheet_insert_image_buffer_opt(this.handle, row,
357 					col, buf, bufSize, options
358 				)
359 				== LXW_NO_ERROR
360 			);
361 	}
362 
363 	void insertChart(RowType row, ColType col, Chart chart) {
364 		enforce(worksheet_insert_chart(this.handle, row, col,
365 					chart.handle) == LXW_NO_ERROR);
366 	}
367 
368 	void insertChartOpt(RowType row, ColType col, Chart chart,
369 			lxw_image_options* options)
370 	{
371 		enforce(worksheet_insert_chart_opt(this.handle, row,
372 					col, chart.handle, options
373 				)
374 				== LXW_NO_ERROR
375 			);
376 	}
377 
378 	void mergeRange(RowType firstRow, ColType firstCol, RowType lastRow,
379 			ColType lastCol, string str)
380 	{
381 		this.mergeRangeImpl(firstRow, firstCol, lastRow,
382 			lastCol, str, Format(null));
383 	}
384 
385 	version(No_Overloads_Or_Templates) {
386 		void mergeRangeFormat(RowType firstRow, ColType firstCol,
387 				RowType lastRow, ColType lastCol, string str, Format f)
388 		{
389 			this.mergeRangeImpl(firstRow, firstCol, lastRow,
390 				lastCol, str, f);
391 		}
392 	} else {
393 		void mergeRange(RowType firstRow, ColType firstCol, RowType lastRow,
394 				ColType lastCol, string str, Format f)
395 		{
396 			this.mergeRangeImpl(firstRow, firstCol, lastRow,
397 				lastCol, str, f);
398 		}
399 	}
400 
401 	private void mergeRangeImpl(RowType firstRow, ColType firstCol,
402 			RowType lastRow, ColType lastCol, string str, Format format)
403 	{
404 		enforce(worksheet_merge_range(this.handle, firstRow, firstCol,
405 					lastRow, lastCol, toStringz(str), format.handle
406 				)
407 				== LXW_NO_ERROR
408 			);
409 	}
410 
411 	void autofilter(RowType firstRow, ColType firstCol, RowType lastRow,
412 			ColType lastCol) {
413 		enforce(worksheet_autofilter(this.handle, firstRow, firstCol,
414 					lastRow, lastCol) == LXW_NO_ERROR);
415 	}
416 
417 	void dataValidationCell(RowType row, ColType col,
418 			lxw_data_validation* validator)
419 	{
420 		enforce(worksheet_data_validation_cell(this.handle, row,
421 					col, validator
422 				)
423 				== LXW_NO_ERROR
424 			);
425 	}
426 
427 	void dataValidationRange(RowType firstRow, ColType firstCol,
428 			RowType lastRow, ColType lastCol, lxw_data_validation* validator)
429 	{
430 		enforce(worksheet_data_validation_range(this.handle, firstRow,
431 					firstCol, lastRow, lastCol, validator
432 				)
433 				== LXW_NO_ERROR
434 			);
435 	}
436 
437 	void activate() @nogc nothrow {
438 		worksheet_activate(this.handle);
439 	}
440 
441 	void select() @nogc nothrow {
442 		worksheet_select(this.handle);
443 	}
444 
445 	void hide() @nogc nothrow {
446 		worksheet_hide(this.handle);
447 	}
448 
449 	void setFirstSheet() @nogc nothrow {
450 		worksheet_set_first_sheet(this.handle);
451 	}
452 
453 	void freezePanes(RowType row, ColType col) @nogc nothrow {
454 		worksheet_freeze_panes(this.handle, row, col);
455 	}
456 
457 	void splitPanes(double vertical, double horizontal) @nogc nothrow {
458 		worksheet_split_panes(this.handle, vertical, horizontal);
459 	}
460 
461 	void setSelection(RowType firstRow, ColType firstCol, RowType lastRow,
462 			ColType lastCol) @nogc nothrow
463 	{
464 		worksheet_set_selection(this.handle, firstRow, firstCol, lastRow,
465 				lastCol
466 			);
467 	}
468 
469 	void setLandscape() @nogc nothrow {
470 		worksheet_set_landscape(this.handle);
471 	}
472 
473 	void setPortrait() @nogc nothrow {
474 		worksheet_set_portrait(this.handle);
475 	}
476 
477 	void setPageView() @nogc nothrow {
478 		worksheet_set_page_view(this.handle);
479 	}
480 
481 	void setPaper(ubyte paperType) @nogc nothrow {
482 		worksheet_set_paper(this.handle, paperType);
483 	}
484 
485 	void setMargins(double left, double right, double top, double bottom)
486 			@nogc nothrow
487 	{
488 		worksheet_set_margins(this.handle, left, right, top, bottom);
489 	}
490 
491 	void setHeader(string header) {
492 		enforce(worksheet_set_header(this.handle, toStringz(header))
493 				== LXW_NO_ERROR
494 			);
495 	}
496 
497 	void setFooter(string footer) {
498 		enforce(worksheet_set_footer(this.handle, toStringz(footer))
499 				== LXW_NO_ERROR
500 			);
501 	}
502 
503 	void setHeaderOpt(string header, lxw_header_footer_options* options) {
504 		enforce(worksheet_set_header_opt(this.handle, toStringz(header),
505 					options
506 				)
507 				== LXW_NO_ERROR
508 			);
509 	}
510 
511 	void setFooterOpt(string footer, lxw_header_footer_options* options) {
512 		enforce(worksheet_set_footer_opt(this.handle, toStringz(footer),
513 					options
514 				)
515 				== LXW_NO_ERROR
516 			);
517 	}
518 
519 	void setHPagebreaks(RowType[] row) {
520 		enforce(worksheet_set_h_pagebreaks(this.handle, row.ptr)
521 				== LXW_NO_ERROR
522 			);
523 	}
524 
525 	void setVPagebreaks(ColType[] col) {
526 		enforce(worksheet_set_v_pagebreaks(this.handle, col.ptr)
527 				== LXW_NO_ERROR
528 			);
529 	}
530 
531 	void printAcross() @nogc nothrow {
532 		worksheet_print_across(this.handle);
533 	}
534 
535 	void setZoom(ushort scale) @nogc nothrow {
536 		worksheet_set_zoom(this.handle, scale);
537 	}
538 
539 	void gridlines(ubyte option) @nogc nothrow {
540 		worksheet_gridlines(this.handle, option);
541 	}
542 
543 	void centerHorizontally() @nogc nothrow {
544 		worksheet_center_horizontally(this.handle);
545 	}
546 
547 	void centerVertically() @nogc nothrow {
548 		worksheet_center_vertically(this.handle);
549 
550 	}
551 	void printRowColHeaders() @nogc nothrow {
552 		worksheet_print_row_col_headers(this.handle);
553 	}
554 
555 	void repeatRows(RowType firstRow, RowType lastRow) {
556 		enforce(worksheet_repeat_rows(this.handle, firstRow, lastRow) ==
557 				LXW_NO_ERROR);
558 	}
559 
560 	void repeatColumns(ColType firstCol, ColType lastCol) {
561 		enforce(worksheet_repeat_columns(this.handle, firstCol, lastCol)
562 				== LXW_NO_ERROR
563 			);
564 	}
565 
566 	void printArea(RowType firstRow, ColType firstCol, RowType lastRow,
567 			ColType lastCol)
568 	{
569 		enforce(worksheet_print_area(this.handle, firstRow, firstCol, lastRow,
570 					lastCol
571 				)
572 				== LXW_NO_ERROR
573 			);
574 	}
575 
576 	void fitToPages(ushort width, ushort height) @nogc nothrow {
577 		worksheet_fit_to_pages(this.handle, width, height);
578 	}
579 
580 	void setStartPage(ushort startPage) @nogc nothrow {
581 		worksheet_set_start_page(this.handle, startPage);
582 	}
583 
584 	void setPrintScale(ushort scale) @nogc nothrow {
585 		worksheet_set_print_scale(this.handle, scale);
586 	}
587 
588 	void rightToLeft() @nogc nothrow {
589 		worksheet_right_to_left(this.handle);
590 	}
591 
592 	void hideZero() @nogc nothrow {
593 		worksheet_hide_zero(this.handle);
594 	}
595 
596 	void setTabColor(lxw_color_t color) @nogc nothrow {
597 		worksheet_set_tab_color(this.handle, color);
598 	}
599 
600 	void protect(string password, lxw_protection* options) {
601 		worksheet_protect(this.handle, toStringz(password), options);
602 	}
603 
604 	void outlineSettings(ubyte visible, ubyte symbolsBelow,
605 			ubyte symbolsRight, ubyte autoStyle) @nogc nothrow
606 	{
607 		worksheet_outline_settings(this.handle, visible, symbolsBelow,
608 			symbolsRight, autoStyle);
609 	}
610 
611 	void setDefaultRow(double height, ubyte hideUnusedRows) @nogc nothrow {
612 		worksheet_set_default_row(this.handle, height, hideUnusedRows);
613 	}
614 }