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 			["DateTime", "DateTime", ""],
25 			["DateTime", "DateTime", "Format"],
26 			["Date", "Date", ""],
27 			["Date", "Date", "Format"],
28 			["TimeOfDay", "TimeOfDay", ""],
29 			["TimeOfDay", "TimeOfDay", "Format"],
30 			["Formula", "string", ""],
31 			["Formula", "string", "Format"],
32 			["Url", "string", ""],
33 			["Url", "string", "Format"],
34 			["RichString", "lxw_rich_string_tuple**", ""],
35 			["RichString", "lxw_rich_string_tuple**", "Format"],
36 		];
37 	string ret;
38 	version(No_Overloads_Or_Templates) {
39 		immutable overloads = false;
40 		ret ~= `
41 	void writeBlank(RowType row, ColType col) @safe {
42 		this.writeBlankImpl(row, col, Format(null));
43 	}
44 
45 	void writeBlankFormat(RowType row, ColType col, Format f) @safe {
46 		this.writeBlankImpl(row, col, f);
47 	}
48 
49 	void writeFormulaNum(RowType row, ColType col, string formula, double num)
50 			@safe
51 	{
52 		this.writeFormulaNumImpl(row, col, formula, num, Format(null));
53 	}
54 
55 	void writeFormulaNumFormat(RowType row, ColType col, string formula,
56 			double num, Format f) @safe
57 	{
58 		this.writeFormulaNumImpl(row, col, formula, num, f);
59 	}
60 `;
61 
62 	} else {
63 		immutable overloads = true;
64 		ret ~= `
65 	void writeBlank(RowType row, ColType col) @safe {
66 		this.writeBlankImpl(row, col, Format(null));
67 	}
68 
69 	void writeBlank(RowType row, ColType col, Format f) @safe {
70 		this.writeBlankImpl(row, col, f);
71 	}
72 
73 	void writeFormulaNum(RowType row, ColType col, string formula, double num)
74 			@safe
75 	{
76 		this.writeFormulaNumImpl(row, col, formula, num, Format(null));
77 	}
78 
79 	void writeFormulaNum(RowType row, ColType col, string formula,
80 			double num, Format f) @safe
81 	{
82 		this.writeFormulaNumImpl(row, col, formula, num, f);
83 	}
84 `;
85 	}
86 
87 	foreach(string[3] f; fun) {
88 		bool addi = !f[2].empty;
89 		ret ~= format(
90 				"void write%s%s(RowType row, ColType col, %s value%s) @safe {\n",
91 				f[0],
92 				!overloads && addi ? "Format" : "",
93 				f[1], addi ? ", Format f" : ""
94 			);
95 		ret ~= format("\tthis.write%sImpl(row, col, value%s);\n}\n\n",
96 				f[0], addi ? ", f": ", Format(null)"
97 			);
98 	}
99 	return ret;
100 }
101 
102 struct Column {
103 	WorksheetFluent* wsf;
104 
105 	this(WorksheetFluent* wsf) @safe {
106 		this.wsf = wsf;
107 	}
108 
109 	Column writeInt(long value) @safe {
110 		return this.writeIntFormatted(value, Format(null));
111 	}
112 
113 	Column writeIntFormatted(long value, Format format) @safe {
114 		this.wsf.ws.write(this.wsf.pos.row++, this.wsf.pos.col, value,
115 				format);
116 		return this;
117 	}
118 
119 	Column writeNumber(double value) @safe {
120 		return this.writeNumberFormatted(value, Format(null));
121 	}
122 
123 	Column writeNumberFormatted(double value, Format format) @safe {
124 		this.wsf.ws.write(this.wsf.pos.row++, this.wsf.pos.col, value,
125 				format);
126 		return this;
127 	}
128 
129 	Column writeString(string value) @safe {
130 		return this.writeStringFormatted(value, Format(null));
131 	}
132 
133 	Column writeStringFormatted(string value, Format format) @safe {
134 		this.wsf.ws.write(this.wsf.pos.row++, this.wsf.pos.col, value,
135 				format);
136 		return this;
137 	}
138 
139 	WorksheetFluent terminate() @safe {
140 		this.wsf.pos.row = 0;
141 		this.wsf.pos.col++;
142 		return *this.wsf;
143 	}
144 }
145 
146 struct Row {
147 	WorksheetFluent* wsf;
148 
149 	this(WorksheetFluent* wsf) @safe {
150 		this.wsf = wsf;
151 	}
152 
153 	Row writeInt(long value) @safe {
154 		return this.writeIntFormatted(value, Format(null));
155 	}
156 
157 	Row writeIntFormatted(long value, Format format) @safe {
158 		this.wsf.ws.write(this.wsf.pos.row, this.wsf.pos.col++, value,
159 				format);
160 		return this;
161 	}
162 
163 	Row writeNumber(double value) @safe {
164 		return this.writeNumberFormatted(value, Format(null));
165 	}
166 
167 	Row writeNumberFormatted(double value, Format format) @safe {
168 		this.wsf.ws.write(this.wsf.pos.row, this.wsf.pos.col++, value,
169 				format);
170 		return this;
171 	}
172 
173 	Row writeString(string value) @safe {
174 		return this.writeStringFormatted(value, Format(null));
175 	}
176 
177 	Row writeStringFormatted(string value, Format format) @safe {
178 		this.wsf.ws.write(this.wsf.pos.row, this.wsf.pos.col++, value,
179 				format);
180 		return this;
181 	}
182 
183 	WorksheetFluent terminate() @safe {
184 		this.wsf.pos.row++;
185 		this.wsf.pos.col = 0;
186 		return *this.wsf;
187 	}
188 }
189 
190 struct Position {
191 	RowType row;
192 	ColType col;
193 }
194 
195 struct WorksheetFluent {
196 	import libxlsxd.workbook : WorkbookOpen;
197 	WorkbookOpen* wb;
198 	Worksheet ws;
199 
200 	Position pos;
201 
202 	this(WorkbookOpen* wb, Worksheet ws) @safe {
203 		this.wb = wb;
204 		this.ws = ws;
205 	}
206 
207 	Row startRow() @safe {
208 		return Row(&this);
209 	}
210 
211 	Column startColumn() @safe {
212 		return Column(&this);
213 	}
214 
215 	WorkbookOpen terminate() @safe {
216 		return *this.wb;
217 	}
218 }
219 
220 struct Worksheet {
221 	import core.stdc.config : c_ulong;
222 	import std.datetime;
223 	import std.string : toStringz;
224 	import std.exception : enforce;
225 	lxw_worksheet* handle;
226 
227 	private Format* dtf;
228 	private Format* df;
229 	private Format* tf;
230 
231 	this(lxw_worksheet* handle, Format* dtf, Format* df, Format* tf)
232 			@nogc nothrow @safe
233 	{
234 		this.handle = handle;
235 		this.dtf = dtf;
236 		this.df = df;
237 		this.tf = tf;
238 	}
239 
240 	mixin(genWriteOverloads());
241 
242 	void write(T)(RowType row, ColType col, T value) @safe {
243 		this.write(row, col, value, Format(null));
244 	}
245 
246 	void write(T)(RowType row, ColType col, T value, Format format) @trusted {
247 		import std.traits : isIntegral, isFloatingPoint, isSomeString;
248 		static if((isFloatingPoint!T || isIntegral!T) && !is(T == bool)) {
249 			this.writeNumberImpl(row, col, value, format);
250 		} else static if(isSomeString!T) {
251 			this.writeStringImpl(row, col, value, format);
252 		} else static if(is(T == TimeOfDay)) {
253 			format = format.handle == null ? *this.tf : format;
254 			Datetime theTime;
255 			version(No_Overloads_Or_Templates) {
256 				theTime = Datetime.fromTimeOfDay(value);
257 			} else {
258 				theTime = Datetime(value);
259 			}
260 			this.writeDatetimeImpl(row, col, theTime, format);
261 		} else static if(is(T == Date)) {
262 			format = format.handle == null ? *this.df : format;
263 			Datetime theTime;
264 			version(No_Overloads_Or_Templates) {
265 				theTime = Datetime.fromDate(value);
266 			} else {
267 				theTime = Datetime(value);
268 			}
269 			this.writeDatetimeImpl(row, col, theTime, format);
270 		} else static if(is(T == DateTime)) {
271 			format = format.handle == null ? *this.dtf : format;
272 			Datetime theTime;
273 			version(No_Overloads_Or_Templates) {
274 				theTime = Datetime.fromDateTime(value);
275 			} else {
276 				theTime = Datetime(value);
277 			}
278 			this.writeDatetimeImpl(row, col, theTime, format);
279 		} else static if(is(T == Datetime)) {
280 			this.writeDatetimeImpl(row, col, value, format);
281 		} else static if(is(T == bool)) {
282 			this.writeBooleanImpl(row, col, value, format);
283 		} else {
284 			static assert(false, "The function 'write' does not support type
285 					'" ~ T.stringof ~ "'");
286 		}
287 	}
288 
289 	size_t writeAndGetWidth(T)(RowType row, ColType col, T value) @safe {
290 		return writeAndGetWidth(row, col, value, Format(null));
291 	}
292 
293 	size_t writeAndGetWidth(T)(RowType row, ColType col, T value,
294 			Format format) @safe
295 	{
296 		import std.traits : isIntegral, isFloatingPoint, isSomeString;
297 		import std.conv : to;
298 		static if((isFloatingPoint!T || isIntegral!T) && !is(T == bool)) {
299 			this.writeNumberImpl(row, col, value, format);
300 			return to!string(value).length;
301 		} else static if(is(T == TimeOfDay)) {
302 			format = format.handle == null ? *this.tf : format;
303 			Datetime theTime;
304 			version(No_Overloads_Or_Templates) {
305 				theTime = Datetime.fromTimeOfday(value);
306 			} else {
307 				theTime = Datetime(value);
308 			}
309 			this.writeDatetimeImpl(row, col, theTime, format);
310 			return to!size_t(8);
311 		} else static if(is(T == Date)) {
312 			format = format.handle == null ? *this.df : format;
313 			Datetime theTime;
314 			version(No_Overloads_Or_Templates) {
315 				theTime = Datetime.fromTimeOfday(value);
316 			} else {
317 				theTime = Datetime(value);
318 			}
319 			this.writeDatetimeImpl(row, col, theTime, format);
320 			return to!size_t(10);
321 		} else static if(is(T == DateTime)) {
322 			format = format.handle == null ? *this.dtf : format;
323 			Datetime theTime;
324 			version(No_Overloads_Or_Templates) {
325 				theTime = Datetime.fromDateTime(value);
326 			} else {
327 				theTime = Datetime(value);
328 			}
329 			this.writeDatetimeImpl(row, col, theTime, format);
330 			return to!size_t(19);
331 		} else static if(isSomeString!T) {
332 			this.writeStringImpl(row, col, value, format);
333 			return value.length;
334 		} else static if(is(T == bool)) {
335 			this.writeBooleanImpl(row, col, value, format);
336 			return value ? 4 : 5;
337 		} else {
338 			static assert(false, "The function 'writeAndGetWidth' does not "
339 					~ " support type '" ~ T.stringof ~ "'");
340 		}
341 	}
342 
343 	void writeIntImpl(RowType row, ColType col, double num,
344 			Format format) @trusted
345 	{
346 		enforce(worksheet_write_number(this.handle, row, col,
347 					num, format.handle) == LXW_NO_ERROR);
348 	}
349 
350 	void writeNumberImpl(RowType row, ColType col, double num,
351 			Format format) @trusted
352 	{
353 		enforce(worksheet_write_number(this.handle, row, col,
354 					num, format.handle) == LXW_NO_ERROR);
355 	}
356 
357 	void writeStringImpl(RowType row, ColType col, string str, Format format)
358 			@trusted
359 	{
360 		enforce(worksheet_write_string(this.handle, row, col,
361 					toStringz(str), format.handle) == LXW_NO_ERROR);
362 	}
363 
364 	private void writeFormulaImpl(RowType row, ColType col, string formula,
365 			Format format) @trusted
366 	{
367 		enforce(worksheet_write_formula(this.handle, row, col,
368 					toStringz(formula), format.handle) == LXW_NO_ERROR);
369 	}
370 
371 	void writeArrayFormula(RowType firstRow, ColType firstCol,
372 			RowType lastRow, ColType lastCol, string formula) @trusted
373 	{
374 		this.writeArrayFormulaImpl(firstRow, firstCol, lastRow, lastCol,
375 				formula, Format(null));
376 	}
377 
378 	version(No_Overloads_Or_Templates) {
379 		void writeArrayFormulaFormat(RowType firstRow, ColType firstCol,
380 				RowType lastRow, ColType lastCol, string formula, Format format)
381 				@trusted
382 		{
383 			this.writeArrayFormulaImpl(firstRow, firstCol, lastRow, lastCol,
384 					formula, format);
385 		}
386 	} else {
387 		void writeArrayFormula(RowType firstRow, ColType firstCol,
388 				RowType lastRow, ColType lastCol, string formula, Format format)
389 				@trusted
390 		{
391 			this.writeArrayFormulaImpl(firstRow, firstCol, lastRow, lastCol,
392 					formula, format);
393 		}
394 	}
395 
396 	private void writeArrayFormulaImpl(RowType firstRow, ColType firstCol,
397 			RowType lastRow, ColType lastCol, string formula, Format format)
398 			@trusted
399 	{
400 		enforce(worksheet_write_array_formula(this.handle, firstRow,
401 					firstCol, lastRow, lastCol, toStringz(formula),
402 					format.handle) == LXW_NO_ERROR);
403 	}
404 
405 	void writeTimeOfDayImpl(RowType row, ColType col, TimeOfDay tod,
406 			Format format) @trusted
407 	{
408 		Datetime theTime;
409 		version(No_Overloads_Or_Templates) {
410 			theTime = Datetime.fromTimeOfDay(tod);
411 		} else {
412 			theTime = Datetime(tod);
413 		}
414 		enforce(worksheet_write_datetime(this.handle, row, col,
415 					&theTime.handle, format.handle) == LXW_NO_ERROR);
416 	}
417 
418 	void writeDateImpl(RowType row, ColType col, Date date,
419 			Format format) @trusted
420 	{
421 		Datetime theTime;
422 		version(No_Overloads_Or_Templates) {
423 			theTime = Datetime.fromDate(date);
424 		} else {
425 			theTime = Datetime(date);
426 		}
427 		enforce(worksheet_write_datetime(this.handle, row, col,
428 					&theTime.handle, format.handle) == LXW_NO_ERROR);
429 	}
430 
431 	void writeDateTimeImpl(RowType row, ColType col, DateTime dt,
432 			Format format) @trusted
433 	{
434 		Datetime theTime;
435 		version(No_Overloads_Or_Templates) {
436 			theTime = Datetime.fromDateTime(dt);
437 		} else {
438 			theTime = Datetime(dt);
439 		}
440 		enforce(worksheet_write_datetime(this.handle, row, col,
441 					&theTime.handle, format.handle) == LXW_NO_ERROR);
442 	}
443 
444 	void writeDatetimeImpl(RowType row, ColType col, Datetime datetime,
445 			Format format) @trusted
446 	{
447 		enforce(worksheet_write_datetime(this.handle, row, col,
448 					&datetime.handle, format.handle) == LXW_NO_ERROR);
449 	}
450 
451 	void writeUrlImpl(RowType row, ColType col, string url, Format format)
452 			@trusted
453 	{
454 		enforce(worksheet_write_url(this.handle, row, col,
455 					toStringz(url), format.handle) == LXW_NO_ERROR);
456 	}
457 
458 	void writeBooleanImpl(RowType row, ColType col, bool value, Format format)
459 			@trusted
460 	{
461 		enforce(worksheet_write_boolean(this.handle, row, col,
462 					value, format.handle) == LXW_NO_ERROR);
463 	}
464 
465 	void writeBlankImpl(RowType row, ColType col, Format format) @trusted {
466 		enforce(worksheet_write_blank(this.handle, row, col,
467 					format.handle) == LXW_NO_ERROR);
468 	}
469 
470 	void writeFormulaNumImpl(RowType row, ColType col, string formula,
471 			double value, Format format) @trusted
472 	{
473 		enforce(worksheet_write_formula_num(this.handle, row,
474 					col, toStringz(formula), format.handle, value
475 				)
476 				== LXW_NO_ERROR
477 			);
478 	}
479 
480 	void writeRichStringImpl(RowType row, ColType col,
481 			lxw_rich_string_tuple** rst, Format format) @trusted
482 	{
483 		enforce(worksheet_write_rich_string(this.handle, row,
484 					col, rst, format.handle
485 				)
486 				== LXW_NO_ERROR
487 			);
488 	}
489 
490 	void setRow(RowType row, double height) @safe {
491 		this.setRowImpl(row, height, Format(null));
492 	}
493 
494 	version(No_Overloads_Or_Templates) {
495 		void setRowFormat(RowType row, double height, Format f) @safe {
496 			this.setRowImpl(row, height, f);
497 		}
498 	} else {
499 		void setRow(RowType row, double height, Format f) @safe {
500 			this.setRowImpl(row, height, f);
501 		}
502 	}
503 
504 	private void setRowImpl(RowType row, double height, Format format)
505 			@trusted
506 	{
507 		enforce(worksheet_set_row(this.handle, row, height, format.handle)
508 				== LXW_NO_ERROR
509 			);
510 	}
511 
512 	void setRowOpt(RowType row, double height, lxw_row_col_options* options)
513 			@trusted
514 	{
515 		this.setRowOptImpl(row, height, options, Format(null));
516 	}
517 
518 	version(No_Overloads_Or_Templates) {
519 		void setRowOptFormat(RowType row, double height,
520 				lxw_row_col_options* options, Format f) @trusted
521 		{
522 			this.setRowOptImpl(row, height, options, f);
523 		}
524 	} else {
525 		void setRowOpt(RowType row, double height,
526 				lxw_row_col_options* options, Format f) @trusted
527 		{
528 			this.setRowOptImpl(row, height, options, f);
529 		}
530 	}
531 
532 	private void setRowOptImpl(RowType row, double height,
533 			lxw_row_col_options* options, Format format) @trusted
534 	{
535 		enforce(worksheet_set_row_opt(this.handle, row, height,
536 					format.handle, options) == LXW_NO_ERROR);
537 	}
538 
539 	void setColumn(ColType firstCol, ColType lastCol, double width) @trusted {
540 		this.setColumnImpl(firstCol, lastCol, width, Format(null));
541 	}
542 
543 	version(No_Overloads_Or_Templates) {
544 		void setColumnFormat(ColType firstCol, ColType lastCol, double width,
545 				Format f) @trusted
546 		{
547 			this.setColumnImpl(firstCol, lastCol, width, f);
548 		}
549 	} else {
550 		void setColumn(ColType firstCol, ColType lastCol, double width,
551 				Format f) @trusted
552 		{
553 			this.setColumnImpl(firstCol, lastCol, width, f);
554 		}
555 	}
556 
557 	private void setColumnImpl(ColType firstCol, ColType lastCol, double width,
558 			Format format) @trusted
559 	{
560 		enforce(worksheet_set_column(this.handle, firstCol, lastCol,
561 					width, format.handle
562 				)
563 				== LXW_NO_ERROR
564 			);
565 	}
566 
567 	void setColumnOpt(ColType firstCol, ColType lastCol, double width,
568 			lxw_row_col_options* options) @trusted
569 	{
570 		this.setColumnOptImpl(firstCol, lastCol, width, options, Format(null));
571 	}
572 
573 	version(No_Overloads_Or_Templates) {
574 		void setColumnOptFormat(ColType firstCol, ColType lastCol, double width,
575 				lxw_row_col_options* options, Format f) @trusted
576 		{
577 			this.setColumnOptImpl(firstCol, lastCol, width, options, f);
578 		}
579 	} else {
580 		void setColumnOpt(ColType firstCol, ColType lastCol, double width,
581 				lxw_row_col_options* options, Format f) @trusted
582 		{
583 			this.setColumnOptImpl(firstCol, lastCol, width, options, f);
584 		}
585 	}
586 
587 	private void setColumnOptImpl(ColType firstCol, ColType lastCol,
588 			double width, lxw_row_col_options* options, Format format) @trusted
589 	{
590 		enforce(worksheet_set_column_opt(this.handle, firstCol, lastCol,
591 					width, format.handle, options)
592 				== LXW_NO_ERROR
593 			);
594 	}
595 
596 	void insertImage(RowType row, ColType col, string filename) @trusted {
597 		enforce(worksheet_insert_image(this.handle, row, col,
598 					toStringz(filename)
599 				)
600 				== LXW_NO_ERROR
601 			);
602 	}
603 
604 	void insertImageOpt(RowType row, ColType col, string filename,
605 			lxw_image_options* options) @trusted
606 	{
607 		enforce(worksheet_insert_image_opt(this.handle, row, col,
608 					toStringz(filename), options
609 				)
610 				== LXW_NO_ERROR
611 			);
612 	}
613 
614 	void insertImageBuffer(RowType row, ColType col, const(ubyte)* buf,
615 			size_t bufSize) @trusted
616 	{
617 		enforce(worksheet_insert_image_buffer(this.handle, row,
618 					col, buf, cast(c_ulong)bufSize
619 				)
620 				== LXW_NO_ERROR
621 			);
622 	}
623 
624 	void insertImageBufferOpt(RowType row, ColType col, const(ubyte)* buf,
625 			size_t bufSize, lxw_image_options* options) @trusted
626 	{
627 		enforce(worksheet_insert_image_buffer_opt(this.handle, row,
628 					col, buf, cast(c_ulong)bufSize, options
629 				)
630 				== LXW_NO_ERROR
631 			);
632 	}
633 
634 	void insertChart(RowType row, ColType col, Chart chart) @trusted {
635 		enforce(worksheet_insert_chart(this.handle, row, col,
636 					chart.handle) == LXW_NO_ERROR);
637 	}
638 
639 	void insertChartOpt(RowType row, ColType col, Chart chart,
640 			lxw_image_options* options) @trusted
641 	{
642 		enforce(worksheet_insert_chart_opt(this.handle, row,
643 					col, chart.handle, options
644 				)
645 				== LXW_NO_ERROR
646 			);
647 	}
648 
649 	void mergeRange(RowType firstRow, ColType firstCol, RowType lastRow,
650 			ColType lastCol, string str) @trusted
651 	{
652 		this.mergeRangeImpl(firstRow, firstCol, lastRow,
653 			lastCol, str, Format(null));
654 	}
655 
656 	version(No_Overloads_Or_Templates) {
657 		void mergeRangeFormat(RowType firstRow, ColType firstCol,
658 				RowType lastRow, ColType lastCol, string str, Format f) @trusted
659 		{
660 			this.mergeRangeImpl(firstRow, firstCol, lastRow,
661 				lastCol, str, f);
662 		}
663 	} else {
664 		void mergeRange(RowType firstRow, ColType firstCol, RowType lastRow,
665 				ColType lastCol, string str, Format f) @trusted
666 		{
667 			this.mergeRangeImpl(firstRow, firstCol, lastRow,
668 				lastCol, str, f);
669 		}
670 	}
671 
672 	private void mergeRangeImpl(RowType firstRow, ColType firstCol,
673 			RowType lastRow, ColType lastCol, string str, Format format)
674 			@trusted
675 	{
676 		enforce(worksheet_merge_range(this.handle, firstRow, firstCol,
677 					lastRow, lastCol, toStringz(str), format.handle
678 				)
679 				== LXW_NO_ERROR
680 			);
681 	}
682 
683 	void autofilter(RowType firstRow, ColType firstCol, RowType lastRow,
684 			ColType lastCol) @trusted
685 	{
686 		enforce(worksheet_autofilter(this.handle, firstRow, firstCol,
687 					lastRow, lastCol) == LXW_NO_ERROR);
688 	}
689 
690 	void dataValidationCell(RowType row, ColType col,
691 			lxw_data_validation* validator) @trusted
692 	{
693 		enforce(worksheet_data_validation_cell(this.handle, row,
694 					col, validator
695 				)
696 				== LXW_NO_ERROR
697 			);
698 	}
699 
700 	void dataValidationRange(RowType firstRow, ColType firstCol,
701 			RowType lastRow, ColType lastCol, lxw_data_validation* validator)
702 			@trusted
703 	{
704 		enforce(worksheet_data_validation_range(this.handle, firstRow,
705 					firstCol, lastRow, lastCol, validator
706 				)
707 				== LXW_NO_ERROR
708 			);
709 	}
710 
711 	void activate() @nogc nothrow @trusted {
712 		worksheet_activate(this.handle);
713 	}
714 
715 	void select() @nogc nothrow @trusted {
716 		worksheet_select(this.handle);
717 	}
718 
719 	void hide() @nogc nothrow @trusted {
720 		worksheet_hide(this.handle);
721 	}
722 
723 	void setFirstSheet() @nogc nothrow @trusted {
724 		worksheet_set_first_sheet(this.handle);
725 	}
726 
727 	void freezePanes(RowType row, ColType col) @nogc nothrow @trusted {
728 		worksheet_freeze_panes(this.handle, row, col);
729 	}
730 
731 	void splitPanes(double vertical, double horizontal) @nogc nothrow @trusted {
732 		worksheet_split_panes(this.handle, vertical, horizontal);
733 	}
734 
735 	void setSelection(RowType firstRow, ColType firstCol, RowType lastRow,
736 			ColType lastCol) @nogc nothrow @trusted
737 	{
738 		worksheet_set_selection(this.handle, firstRow, firstCol, lastRow,
739 				lastCol
740 			);
741 	}
742 
743 	void setLandscape() @nogc nothrow @trusted {
744 		worksheet_set_landscape(this.handle);
745 	}
746 
747 	void setPortrait() @nogc nothrow @trusted {
748 		worksheet_set_portrait(this.handle);
749 	}
750 
751 	void setPageView() @nogc nothrow @trusted {
752 		worksheet_set_page_view(this.handle);
753 	}
754 
755 	void setPaper(ubyte paperType) @nogc nothrow @trusted {
756 		worksheet_set_paper(this.handle, paperType);
757 	}
758 
759 	void setMargins(double left, double right, double top, double bottom)
760 			@nogc nothrow @trusted
761 	{
762 		worksheet_set_margins(this.handle, left, right, top, bottom);
763 	}
764 
765 	void setHeader(string header) @trusted {
766 		enforce(worksheet_set_header(this.handle, toStringz(header))
767 				== LXW_NO_ERROR
768 			);
769 	}
770 
771 	void setFooter(string footer) @trusted {
772 		enforce(worksheet_set_footer(this.handle, toStringz(footer))
773 				== LXW_NO_ERROR
774 			);
775 	}
776 
777 	void setHeaderOpt(string header, lxw_header_footer_options* options)
778 			@trusted
779 	{
780 		enforce(worksheet_set_header_opt(this.handle, toStringz(header),
781 					options
782 				)
783 				== LXW_NO_ERROR
784 			);
785 	}
786 
787 	void setFooterOpt(string footer, lxw_header_footer_options* options)
788 			@trusted
789 	{
790 		enforce(worksheet_set_footer_opt(this.handle, toStringz(footer),
791 					options
792 				)
793 				== LXW_NO_ERROR
794 			);
795 	}
796 
797 	void setHPagebreaks(RowType[] row) @trusted {
798 		enforce(worksheet_set_h_pagebreaks(this.handle, row.ptr)
799 				== LXW_NO_ERROR
800 			);
801 	}
802 
803 	void setVPagebreaks(ColType[] col) @trusted {
804 		enforce(worksheet_set_v_pagebreaks(this.handle, col.ptr)
805 				== LXW_NO_ERROR
806 			);
807 	}
808 
809 	void printAcross() @nogc nothrow @trusted {
810 		worksheet_print_across(this.handle);
811 	}
812 
813 	void setZoom(ushort scale) @nogc nothrow @trusted {
814 		worksheet_set_zoom(this.handle, scale);
815 	}
816 
817 	void gridlines(ubyte option) @nogc nothrow @trusted {
818 		worksheet_gridlines(this.handle, option);
819 	}
820 
821 	void centerHorizontally() @nogc nothrow @trusted {
822 		worksheet_center_horizontally(this.handle);
823 	}
824 
825 	void centerVertically() @nogc nothrow @trusted {
826 		worksheet_center_vertically(this.handle);
827 
828 	}
829 	void printRowColHeaders() @nogc nothrow @trusted {
830 		worksheet_print_row_col_headers(this.handle);
831 	}
832 
833 	void repeatRows(RowType firstRow, RowType lastRow) @trusted {
834 		enforce(worksheet_repeat_rows(this.handle, firstRow, lastRow) ==
835 				LXW_NO_ERROR);
836 	}
837 
838 	void repeatColumns(ColType firstCol, ColType lastCol) @trusted {
839 		enforce(worksheet_repeat_columns(this.handle, firstCol, lastCol)
840 				== LXW_NO_ERROR
841 			);
842 	}
843 
844 	void printArea(RowType firstRow, ColType firstCol, RowType lastRow,
845 			ColType lastCol) @trusted
846 	{
847 		enforce(worksheet_print_area(this.handle, firstRow, firstCol, lastRow,
848 					lastCol
849 				)
850 				== LXW_NO_ERROR
851 			);
852 	}
853 
854 	void fitToPages(ushort width, ushort height) @nogc nothrow @trusted {
855 		worksheet_fit_to_pages(this.handle, width, height);
856 	}
857 
858 	void setStartPage(ushort startPage) @nogc nothrow @trusted {
859 		worksheet_set_start_page(this.handle, startPage);
860 	}
861 
862 	void setPrintScale(ushort scale) @nogc nothrow @trusted {
863 		worksheet_set_print_scale(this.handle, scale);
864 	}
865 
866 	void rightToLeft() @nogc nothrow @trusted {
867 		worksheet_right_to_left(this.handle);
868 	}
869 
870 	void hideZero() @nogc nothrow @trusted {
871 		worksheet_hide_zero(this.handle);
872 	}
873 
874 	void setTabColor(lxw_color_t color) @nogc nothrow @trusted {
875 		worksheet_set_tab_color(this.handle, color);
876 	}
877 
878 	void protect(string password, lxw_protection* options) @trusted {
879 		worksheet_protect(this.handle, toStringz(password), options);
880 	}
881 
882 	void outlineSettings(ubyte visible, ubyte symbolsBelow,
883 			ubyte symbolsRight, ubyte autoStyle) @nogc nothrow @trusted
884 	{
885 		worksheet_outline_settings(this.handle, visible, symbolsBelow,
886 			symbolsRight, autoStyle);
887 	}
888 
889 	void setDefaultRow(double height, ubyte hideUnusedRows) @nogc nothrow
890 			@trusted
891 	{
892 		worksheet_set_default_row(this.handle, height, hideUnusedRows);
893 	}
894 }