1
2 /*
3 * dao.c:
4 *
5 * Authors:
6 * Jukka-Pekka Iivonen <jiivonen@hutcs.cs.hut.fi>
7 * Andreas J. Guelzow <aguelzow@taliesin.ca>
8 *
9 * (C) Copyright 2000, 2001 by Jukka-Pekka Iivonen <jiivonen@hutcs.cs.hut.fi>
10 * (C) Copyright 2001, 2002 by Andreas J. Guelzow <aguelzow@taliesin.ca>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses/>.
24 */
25
26 #include <gnumeric-config.h>
27 #include <tools/dao.h>
28
29 #include <expr.h>
30 #include <value.h>
31 #include <cell.h>
32 #include <sheet.h>
33 #include <ranges.h>
34 #include <style.h>
35 #include <sheet-style.h>
36 #include <workbook.h>
37 #include <workbook-view.h>
38 #include <workbook-control.h>
39 #include <command-context.h>
40 #include <gnm-format.h>
41 #include <sheet-merge.h>
42 #include <sheet-object-cell-comment.h>
43 #include <style-color.h>
44 #include <style-border.h>
45 #include <graph.h>
46 #include <goffice/goffice.h>
47
48 #include <glib.h>
49 #include <glib/gi18n-lib.h>
50 #include <string.h>
51 #include <time.h>
52 #include <parse-util.h>
53
54 /**
55 * dao_init: (skip)
56 * @dao:
57 * @type:
58 *
59 * Initialize dao to given type.
60 *
61 **/
62
63 data_analysis_output_t *
dao_init(data_analysis_output_t * dao,data_analysis_output_type_t type)64 dao_init (data_analysis_output_t *dao,
65 data_analysis_output_type_t type)
66 {
67 if (dao == NULL) {
68 dao = g_new (data_analysis_output_t, 1);
69 dao->use_gfree = TRUE;
70 } else
71 dao->use_gfree = FALSE;
72
73 dao->type = type;
74 dao->start_col = 0;
75 dao->start_row = 0;
76 dao->offset_col = 0;
77 dao->offset_row = 0;
78 dao->cols = 1; /* Fixed in dao_prepare_output */
79 dao->rows = 1;
80 dao->sheet = NULL;
81 dao->autofit_flag = TRUE;
82 dao->autofit_noshrink = TRUE;
83 dao->clear_outputrange = TRUE;
84 dao->retain_format = FALSE;
85 dao->retain_comments = FALSE;
86 dao->put_formulas = FALSE;
87 dao->wbc = NULL;
88 dao->sos = NULL;
89 dao->omit_so = FALSE;
90
91 return dao;
92 }
93
94 /**
95 * dao_init_new_sheet: (skip)
96 * @dao:
97 *
98 **/
99 data_analysis_output_t *
dao_init_new_sheet(data_analysis_output_t * dao)100 dao_init_new_sheet (data_analysis_output_t *dao)
101 {
102 return dao_init (dao, NewSheetOutput);
103 }
104
dao_free(data_analysis_output_t * dao)105 void dao_free (data_analysis_output_t *dao)
106 {
107 g_slist_free_full (dao->sos, g_object_unref);
108 dao->sos = NULL;
109
110 if (dao->use_gfree)
111 g_free (dao);
112 }
113
114 /**
115 * dao_load_from_value: (skip)
116 * @dao:
117 * @output_range:
118 *
119 **/
120 data_analysis_output_t *
dao_load_from_value(data_analysis_output_t * dao,GnmValue * output_range)121 dao_load_from_value (data_analysis_output_t *dao,
122 GnmValue *output_range)
123 {
124 g_return_val_if_fail (output_range != NULL, dao);
125 g_return_val_if_fail (VALUE_IS_CELLRANGE (output_range), dao);
126
127 dao->start_col = output_range->v_range.cell.a.col;
128 dao->start_row = output_range->v_range.cell.a.row;
129 dao->cols = output_range->v_range.cell.b.col
130 - output_range->v_range.cell.a.col + 1;
131 dao->rows = output_range->v_range.cell.b.row
132 - output_range->v_range.cell.a.row + 1;
133 dao->sheet = output_range->v_range.cell.a.sheet;
134
135 return dao;
136 }
137
138 /**
139 * dao_range_name:
140 * @dao:
141 *
142 * Provides the name of the output range
143 * The caller has to dispose of the name
144 *
145 **/
146
147 static char *
dao_range_name(data_analysis_output_t * dao)148 dao_range_name (data_analysis_output_t *dao)
149 {
150 GnmRange range;
151 range_init (&range, dao->start_col, dao->start_row,
152 dao->start_col + dao->cols - 1,
153 dao->start_row + dao->rows - 1);
154
155 return undo_range_name (dao->sheet, &range);
156 }
157
158 /**
159 * dao_command_descriptor:
160 * @dao:
161 * @format:
162 * @result:
163 *
164 * Uses format to provide a string to be used as command descriptor for
165 * undo/redo
166 *
167 **/
168
169 char *
dao_command_descriptor(data_analysis_output_t * dao,char const * format,gpointer result)170 dao_command_descriptor (data_analysis_output_t *dao, char const *format,
171 gpointer result)
172 {
173 char *rangename = NULL;
174 char **text = result;
175
176 g_return_val_if_fail (result != NULL, NULL);
177
178 g_free (*text);
179 switch (dao->type) {
180 case NewSheetOutput:
181 *text = g_strdup_printf (format, _("New Sheet"));
182 break;
183 case NewWorkbookOutput:
184 *text = g_strdup_printf (format, _("New Workbook"));
185 break;
186 case RangeOutput:
187 default:
188 rangename = dao_range_name (dao);
189 *text = g_strdup_printf (format, rangename);
190 g_free (rangename);
191 break;
192 }
193 return *text;
194 }
195
196 /**
197 * dao_adjust:
198 * @dao:
199 * @cols:
200 * @rows:
201 *
202 * shrinks the dao to the given cols/rows
203 * (or enlarges it if dao was a singleton)
204 *
205 **/
206
207 void
dao_adjust(data_analysis_output_t * dao,gint cols,gint rows)208 dao_adjust (data_analysis_output_t *dao, gint cols, gint rows)
209 {
210 int max_rows, max_cols;
211
212 if (dao->cols == 1 && dao->rows == 1) {
213 if (cols != -1)
214 dao->cols = cols;
215 if (rows != -1)
216 dao->rows = rows;
217 } else {
218 if (cols != -1)
219 dao->cols = MIN (cols, dao->cols);
220 if (rows != -1)
221 dao->rows = MIN (rows, dao->rows);
222 }
223
224 if (dao->sheet) {
225 max_rows = gnm_sheet_get_max_rows (dao->sheet) - dao->start_row;
226 max_cols = gnm_sheet_get_max_cols (dao->sheet) - dao->start_col;
227 } else {
228 /* In case of NewSheetOutput and NewWorkbookOutput */
229 /* this is called before we actually create the */
230 /* new sheet and/or workbook */
231 Sheet *old_sheet = wb_control_cur_sheet (dao->wbc);
232 max_rows = gnm_sheet_get_max_rows (old_sheet) - dao->start_row;
233 max_cols = gnm_sheet_get_max_cols (old_sheet) - dao->start_col;
234 }
235
236 if (dao->cols > max_cols)
237 dao->cols = max_cols;
238 if (dao->rows > max_rows)
239 dao->rows = max_rows;
240 }
241
242 /**
243 * dao_prepare_output:
244 * @dao:
245 * @name:
246 *
247 * prepares the output by creating a new sheet or workbook as appropriate
248 *
249 **/
250
251 void
dao_prepare_output(WorkbookControl * wbc,data_analysis_output_t * dao,const char * name)252 dao_prepare_output (WorkbookControl *wbc, data_analysis_output_t *dao,
253 const char *name)
254 {
255 char *unique_name;
256
257 if (wbc)
258 dao->wbc = wbc;
259
260 if (dao->type == NewSheetOutput) {
261 Sheet *old_sheet = dao->wbc
262 ? wb_control_cur_sheet (dao->wbc)
263 : dao->sheet;
264 Workbook *wb = old_sheet->workbook;
265 char *name_with_counter = g_strdup_printf ("%s (1)", name);
266 unique_name = workbook_sheet_get_free_name
267 (wb, name_with_counter, FALSE, TRUE);
268 g_free (name_with_counter);
269 dao->rows = gnm_sheet_get_max_rows (old_sheet);
270 dao->cols = gnm_sheet_get_max_cols (old_sheet);
271 dao->sheet = sheet_new (wb, unique_name, dao->cols, dao->rows);
272 g_free (unique_name);
273 dao->start_col = dao->start_row = 0;
274 workbook_sheet_attach (wb, dao->sheet);
275 } else if (dao->type == NewWorkbookOutput) {
276 Sheet *old_sheet = wb_control_cur_sheet (dao->wbc);
277 Workbook *wb = workbook_new ();
278 dao->rows = gnm_sheet_get_max_rows (old_sheet);
279 dao->cols = gnm_sheet_get_max_cols (old_sheet);
280 dao->sheet = sheet_new (wb, name, dao->cols, dao->rows);
281 dao->start_col = dao->start_row = 0;
282 workbook_sheet_attach (wb, dao->sheet);
283 dao->wbc = workbook_control_new_wrapper (dao->wbc, NULL, wb, NULL);
284 }
285
286 if (dao->wbc)
287 wb_view_sheet_focus (wb_control_view (dao->wbc), dao->sheet);
288
289 if (dao->rows == 0 || (dao->rows == 1 && dao->cols == 1))
290 dao->rows = gnm_sheet_get_max_rows (dao->sheet) - dao->start_row;
291 if (dao->cols == 0 || (dao->rows == 1 && dao->cols == 1))
292 dao->cols = gnm_sheet_get_max_cols (dao->sheet) - dao->start_col;
293 dao->offset_col = 0;
294 dao->offset_row = 0;
295 }
296
297 /**
298 * dao_format_output:
299 * @dao:
300 * @cmd:
301 *
302 * Formats the output range according to the settings
303 *
304 *
305 **/
306 gboolean
dao_format_output(data_analysis_output_t * dao,char const * cmd)307 dao_format_output (data_analysis_output_t *dao, char const *cmd)
308 {
309 int clear_flags = 0;
310 GnmRange range;
311
312 range_init (&range, dao->start_col, dao->start_row,
313 dao->start_col + dao->cols - 1,
314 dao->start_row + dao->rows - 1);
315
316 if (dao->type == RangeOutput
317 && sheet_range_splits_region (dao->sheet, &range, NULL,
318 GO_CMD_CONTEXT (dao->wbc), cmd))
319 return TRUE;
320
321 if (dao->clear_outputrange)
322 clear_flags = CLEAR_VALUES | CLEAR_RECALC_DEPS;
323 if (!dao->retain_format)
324 clear_flags |= CLEAR_FORMATS;
325 if (!dao->retain_comments)
326 clear_flags |= CLEAR_COMMENTS;
327
328 sheet_clear_region (dao->sheet,
329 range.start.col, range.start.row,
330 range.end.col, range.end.row,
331 clear_flags | CLEAR_NOCHECKARRAY | CLEAR_MERGES,
332 GO_CMD_CONTEXT (dao->wbc));
333 return FALSE;
334 }
335
336
337 static gboolean
adjust_range(data_analysis_output_t * dao,GnmRange * r)338 adjust_range (data_analysis_output_t *dao, GnmRange *r)
339 {
340 range_normalize (r);
341
342 r->start.col += dao->offset_col + dao->start_col;
343 r->end.col += dao->offset_col + dao->start_col;
344 r->start.row += dao->offset_row + dao->start_row;
345 r->end.row += dao->offset_row + dao->start_row;
346
347 if (dao->type == RangeOutput && (dao->cols > 1 || dao->rows > 1)) {
348 if (r->end.col >= dao->start_col + dao->cols)
349 r->end.col = dao->start_col + dao->cols - 1;
350 if (r->end.row >= dao->start_row + dao->rows)
351 r->end.row = dao->start_row + dao->rows - 1;
352 }
353
354 range_ensure_sanity (r, dao->sheet);
355
356 return ((r->start.col <= r->end.col) && (r->start.row <= r->end.row));
357
358 }
359
360 gboolean
dao_cell_is_visible(data_analysis_output_t * dao,int col,int row)361 dao_cell_is_visible (data_analysis_output_t *dao, int col, int row)
362 {
363 col += dao->offset_col;
364 row += dao->offset_row;
365
366 if (dao->type == RangeOutput &&
367 (dao->cols > 1 || dao->rows > 1) &&
368 (col >= dao->cols || row >= dao->rows))
369 return FALSE;
370
371 col += dao->start_col;
372 row += dao->start_row;
373
374 return (!(col >= gnm_sheet_get_max_cols (dao->sheet) || row >= gnm_sheet_get_max_rows (dao->sheet)));
375 }
376
377
378 /**
379 * dao_set_array_expr: (skip)
380 * @dao:
381 * @col: starting column
382 * @row: starting row
383 * @cols: number of columns
384 * @rows: number of rows
385 * @expr: (transfer full): expression to set
386 *
387 */
388 void
dao_set_array_expr(data_analysis_output_t * dao,int col,int row,int cols,int rows,GnmExpr const * expr)389 dao_set_array_expr (data_analysis_output_t *dao,
390 int col, int row, int cols, int rows,
391 GnmExpr const *expr)
392 {
393 GnmExprTop const *texpr;
394 GnmRange r;
395
396 range_init (&r, col, row, col + cols - 1, row + rows -1);
397
398 if (!adjust_range (dao, &r)) {
399 gnm_expr_free (expr);
400 return;
401 }
402
403 texpr = gnm_expr_top_new (expr);
404 gnm_cell_set_array_formula (dao->sheet,
405 r.start.col, r.start.row,
406 r.end.col, r.end.row,
407 texpr);
408 }
409
410 /**
411 * dao_set_cell_array_expr: (skip)
412 * @dao:
413 * @col: column
414 * @row: row
415 * @expr: (transfer full): expression to set
416 *
417 * Sets a singleton array expression.
418 */
419 void
dao_set_cell_array_expr(data_analysis_output_t * dao,int col,int row,GnmExpr const * expr)420 dao_set_cell_array_expr (data_analysis_output_t *dao, int col, int row,
421 GnmExpr const *expr)
422 {
423 dao_set_array_expr (dao, col, row, 1, 1, expr);
424 }
425
426 /**
427 * dao_set_cell_expr: (skip)
428 * @dao:
429 * @col: column
430 * @row: row
431 * @expr: (transfer full): expression to set
432 *
433 * Sets a singleton array expression.
434 */
435 void
dao_set_cell_expr(data_analysis_output_t * dao,int col,int row,GnmExpr const * expr)436 dao_set_cell_expr (data_analysis_output_t *dao, int col, int row,
437 GnmExpr const *expr)
438 {
439 GnmCell *cell;
440 GnmExprTop const *texpr;
441 GnmRange r;
442
443 range_init (&r, col, row, col, row);
444
445 if (!adjust_range (dao, &r)) {
446 gnm_expr_free (expr);
447 return;
448 }
449
450 cell = sheet_cell_fetch (dao->sheet, r.start.col, r.start.row);
451 texpr = gnm_expr_top_new (expr);
452 gnm_cell_set_expr (cell, texpr);
453 gnm_expr_top_unref (texpr);
454 }
455
456
457 /**
458 * dao_set_cell_value:
459 * @dao:
460 * @col:
461 * @row:
462 * @v: (transfer full):
463 *
464 * set cell to a value
465 *
466 * Note: the rows/cols specification for all dao_set_cell_...
467 * commands are relative to the location of the output
468 **/
469 void
dao_set_cell_value(data_analysis_output_t * dao,int col,int row,GnmValue * v)470 dao_set_cell_value (data_analysis_output_t *dao, int col, int row, GnmValue *v)
471 {
472 GnmCell *cell;
473 GnmRange r;
474
475 range_init (&r, col, row, col, row);
476
477 if (!adjust_range (dao, &r)) {
478 value_release (v);
479 return;
480 }
481
482 cell = sheet_cell_fetch (dao->sheet, r.start.col, r.start.row);
483
484 sheet_cell_set_value (cell, v);
485 }
486
487 /**
488 * dao_set_cell:
489 * @dao:
490 * @col:
491 * @row:
492 * @text:
493 *
494 * set cell to a string
495 *
496 *
497 **/
498 void
dao_set_cell(data_analysis_output_t * dao,int col,int row,const char * text)499 dao_set_cell (data_analysis_output_t *dao, int col, int row, const char *text)
500 {
501 if (text == NULL) {
502 /* FIXME: should we erase instead? */
503 dao_set_cell_value (dao, col, row, value_new_empty ());
504 } else {
505 dao_set_cell_value (dao, col, row, value_new_string (text));
506 }
507 }
508
509
510 /**
511 * dao_set_cell_printf:
512 * @dao:
513 * @col:
514 * @row:
515 * @fmt:
516 * @...:
517 *
518 * create format string and set cell.
519 *
520 **/
521 void
dao_set_cell_printf(data_analysis_output_t * dao,int col,int row,const char * fmt,...)522 dao_set_cell_printf (data_analysis_output_t *dao, int col, int row,
523 const char *fmt, ...)
524 {
525 char *buffer;
526 va_list args;
527
528 va_start (args, fmt);
529 buffer = g_strdup_vprintf (fmt, args);
530 va_end (args);
531
532 dao_set_cell_value (dao, col, row, value_new_string (buffer));
533 g_free (buffer);
534 }
535
536
537 /**
538 * set_cell_float:
539 * @dao:
540 * @col:
541 * @row:
542 * @v:
543 *
544 * set cell to a gnm_float
545 *
546 *
547 **/
548 void
dao_set_cell_float(data_analysis_output_t * dao,int col,int row,gnm_float v)549 dao_set_cell_float (data_analysis_output_t *dao, int col, int row, gnm_float v)
550 {
551 dao_set_cell_value (dao, col, row, value_new_float (v));
552 }
553
554
555 /**
556 * set_cell_int:
557 * @dao:
558 * @col:
559 * @row:
560 * @v:
561 *
562 * set cell to an int
563 *
564 *
565 **/
566 void
dao_set_cell_int(data_analysis_output_t * dao,int col,int row,int v)567 dao_set_cell_int (data_analysis_output_t *dao, int col, int row, int v)
568 {
569 dao_set_cell_value (dao, col, row, value_new_int (v));
570 }
571
572
573 /**
574 * dao_set_cell_na:
575 * @dao:
576 * @col:
577 * @row:
578 *
579 * set cell to NA
580 *
581 *
582 **/
583 void
dao_set_cell_na(data_analysis_output_t * dao,int col,int row)584 dao_set_cell_na (data_analysis_output_t *dao, int col, int row)
585 {
586 dao_set_cell_value (dao, col, row, value_new_error_NA (NULL));
587 }
588
589 /**
590 * dao_set_cell_float_na:
591 * @dao:
592 * @col:
593 * @row:
594 * @v:
595 * @is_valid:
596 *
597 * set cell to a gnm_float or NA as appropriate
598 *
599 *
600 **/
601 void
dao_set_cell_float_na(data_analysis_output_t * dao,int col,int row,gnm_float v,gboolean is_valid)602 dao_set_cell_float_na (data_analysis_output_t *dao, int col, int row,
603 gnm_float v, gboolean is_valid)
604 {
605 if (is_valid) {
606 dao_set_cell_float (dao, col, row, v);
607 } else {
608 dao_set_cell_na (dao, col, row);
609 }
610 }
611
612 /**
613 * dao_set_cell_comment:
614 * @dao:
615 * @col:
616 * @row:
617 * @comment:
618 *
619 * set a cell comment
620 *
621 **/
622 void
dao_set_cell_comment(data_analysis_output_t * dao,int col,int row,const char * comment)623 dao_set_cell_comment (data_analysis_output_t *dao, int col, int row,
624 const char *comment)
625 {
626 char const *author = NULL;
627 GnmRange r;
628
629 range_init (&r, col, row, col, row);
630
631 if (adjust_range (dao, &r))
632 cell_set_comment (dao->sheet, &r.start, author, comment, NULL);
633 }
634
635
636 /**
637 * dao_autofit_these_columns:
638 * @dao:
639 * @from_col:
640 * @to_col:
641 *
642 * Fits the specified columns to their content
643 **/
644 void
dao_autofit_these_columns(data_analysis_output_t * dao,int from_col,int to_col)645 dao_autofit_these_columns (data_analysis_output_t *dao, int from_col, int to_col)
646 {
647 GnmRange r;
648
649 if (!dao->autofit_flag)
650 return;
651
652 range_init_cols (&r, dao->sheet,
653 from_col + dao->start_col,
654 to_col + dao->start_col);
655
656 colrow_autofit (dao->sheet, &r, TRUE,
657 FALSE, dao->autofit_noshrink, FALSE,
658 NULL, NULL);
659 }
660
661 /**
662 * dao_autofit_columns:
663 * @dao:
664 *
665 * fits all columns to their content
666 **/
667 void
dao_autofit_columns(data_analysis_output_t * dao)668 dao_autofit_columns (data_analysis_output_t *dao)
669 {
670 dao_autofit_these_columns (dao, 0, dao->cols - 1);
671 }
672
673 void
dao_autofit_these_rows(data_analysis_output_t * dao,int from_row,int to_row)674 dao_autofit_these_rows (data_analysis_output_t *dao, int from_row, int to_row)
675 {
676 GnmRange r;
677
678 if (!dao->autofit_flag)
679 return;
680
681 range_init_rows (&r, dao->sheet,
682 from_row + dao->start_row,
683 to_row + dao->start_row);
684
685 colrow_autofit (dao->sheet, &r, FALSE,
686 FALSE, dao->autofit_noshrink, FALSE,
687 NULL, NULL);
688 }
689
690 void
dao_autofit_rows(data_analysis_output_t * dao)691 dao_autofit_rows (data_analysis_output_t *dao)
692 {
693 dao_autofit_these_rows (dao, 0, dao->rows - 1);
694 }
695
696
697 /**
698 * dao_set_style:
699 * @dao:
700 * @col1:
701 * @row1:
702 * @col2:
703 * @row2:
704 * @style: (transfer full):
705 *
706 * Applies a partial style to the given region.
707 *
708 **/
709 static void
dao_set_style(data_analysis_output_t * dao,int col1,int row1,int col2,int row2,GnmStyle * mstyle)710 dao_set_style (data_analysis_output_t *dao, int col1, int row1,
711 int col2, int row2, GnmStyle *mstyle)
712 {
713 GnmRange r;
714
715 range_init (&r, col1, row1, col2, row2);
716
717 if (!adjust_range (dao, &r)) {
718 gnm_style_unref (mstyle);
719 return;
720 }
721
722 sheet_style_apply_range (dao->sheet, &r, mstyle);
723 }
724
725 /**
726 * dao_set_bold:
727 * @dao:
728 * @col1:
729 * @row1:
730 * @col2:
731 * @row2:
732 *
733 * sets the given cell range to bold
734 *
735 *
736 **/
737 void
dao_set_bold(data_analysis_output_t * dao,int col1,int row1,int col2,int row2)738 dao_set_bold (data_analysis_output_t *dao, int col1, int row1,
739 int col2, int row2)
740 {
741 GnmStyle *mstyle = gnm_style_new ();
742
743 gnm_style_set_font_bold (mstyle, TRUE);
744
745 dao_set_style (dao, col1, row1, col2, row2, mstyle);
746 }
747
748 /**
749 * dao_set_italic:
750 * @dao:
751 * @col1:
752 * @row1:
753 * @col2:
754 * @row2:
755 *
756 * sets the given cell range to italic
757 *
758 *
759 **/
760 void
dao_set_italic(data_analysis_output_t * dao,int col1,int row1,int col2,int row2)761 dao_set_italic (data_analysis_output_t *dao, int col1, int row1,
762 int col2, int row2)
763 {
764 GnmStyle *mstyle = gnm_style_new ();
765
766 gnm_style_set_font_italic (mstyle, TRUE);
767 dao_set_style (dao, col1, row1, col2, row2, mstyle);
768 }
769
770 /**
771 * dao_set_percent:
772 * @dao:
773 * @col1:
774 * @row1:
775 * @col2:
776 * @row2:
777 *
778 * set the given cell range to percent format
779 *
780 *
781 **/
782 void
dao_set_percent(data_analysis_output_t * dao,int col1,int row1,int col2,int row2)783 dao_set_percent (data_analysis_output_t *dao, int col1, int row1,
784 int col2, int row2)
785 {
786 GnmStyle *mstyle = gnm_style_new ();
787 gnm_style_set_format (mstyle, go_format_default_percentage ());
788 dao_set_style (dao, col1, row1, col2, row2, mstyle);
789 }
790
791 /**
792 * dao_set_date:
793 * @dao:
794 * @col1:
795 * @row1:
796 * @col2:
797 * @row2:
798 *
799 * set the given cell range to date format
800 *
801 *
802 **/
803 void
dao_set_date(data_analysis_output_t * dao,int col1,int row1,int col2,int row2)804 dao_set_date (data_analysis_output_t *dao, int col1, int row1,
805 int col2, int row2)
806 {
807 GnmStyle *mstyle = gnm_style_new ();
808 gnm_style_set_format (mstyle, go_format_default_date ());
809 dao_set_style (dao, col1, row1, col2, row2, mstyle);
810 }
811
812 /**
813 * dao_set_format:
814 * @dao:
815 * @col1:
816 * @row1:
817 * @col2:
818 * @row2:
819 * @format:
820 *
821 * set the given cell range to given format
822 *
823 *
824 **/
825 void
dao_set_format(data_analysis_output_t * dao,int col1,int row1,int col2,int row2,char const * format)826 dao_set_format (data_analysis_output_t *dao, int col1, int row1,
827 int col2, int row2,
828 char const * format)
829 {
830 GOFormat *fmt;
831
832 fmt = go_format_new_from_XL (format);
833 if (go_format_is_invalid (fmt)) {
834 g_warning ("Ignoring invalid format [%s]", format);
835 } else {
836 GnmStyle *mstyle = gnm_style_new ();
837 gnm_style_set_format (mstyle, fmt);
838 dao_set_style (dao, col1, row1, col2, row2, mstyle);
839 }
840 go_format_unref (fmt);
841 }
842
843
844 /**
845 * dao_set_colors:
846 * @dao:
847 * @col1:
848 * @row1:
849 * @col2:
850 * @row2:
851 *
852 * set the given cell range to given background and text colors
853 *
854 *
855 **/
856 void
dao_set_colors(data_analysis_output_t * dao,int col1,int row1,int col2,int row2,GnmColor * fore,GnmColor * back)857 dao_set_colors (data_analysis_output_t *dao, int col1, int row1,
858 int col2, int row2,
859 GnmColor *fore, GnmColor *back)
860 {
861 GnmStyle *mstyle;
862
863 mstyle = gnm_style_new ();
864 if (fore)
865 gnm_style_set_font_color (mstyle, fore);
866 if (back) {
867 gnm_style_set_back_color (mstyle, back);
868 gnm_style_set_pattern (mstyle, 1);
869 }
870 dao_set_style (dao, col1, row1, col2, row2, mstyle);
871 }
872
873 /**
874 * dao_set_align:
875 * @dao:
876 * @col1:
877 * @row1:
878 * @col2:
879 * @row2:
880 *
881 * set the given horizontal and vertical alignment to a cell range
882 *
883 *
884 **/
885 void
dao_set_align(data_analysis_output_t * dao,int col1,int row1,int col2,int row2,GnmHAlign align_h,GnmVAlign align_v)886 dao_set_align (data_analysis_output_t *dao, int col1, int row1,
887 int col2, int row2,
888 GnmHAlign align_h, GnmVAlign align_v)
889 {
890 GnmStyle *mstyle;
891
892 mstyle = gnm_style_new ();
893 gnm_style_set_align_h (mstyle, align_h);
894 gnm_style_set_align_v (mstyle, align_v);
895 dao_set_style (dao, col1, row1, col2, row2, mstyle);
896 }
897
898 /**
899 * dao_set_border:
900 * @dao:
901 * @col1:
902 * @row1:
903 * @col2:
904 * @row2:
905 *
906 *
907 *
908 **/
909 void
dao_set_border(data_analysis_output_t * dao,int col1,int row1,int col2,int row2,GnmStyleElement elem,GnmStyleBorderType border,GnmColor * color,GnmStyleBorderOrientation orientation)910 dao_set_border (data_analysis_output_t *dao, int col1, int row1,
911 int col2, int row2,
912 GnmStyleElement elem, GnmStyleBorderType border,
913 GnmColor *color,
914 GnmStyleBorderOrientation orientation)
915 {
916 GnmStyle *mstyle;
917
918 mstyle = gnm_style_new ();
919 gnm_style_set_border (mstyle, elem,
920 gnm_style_border_fetch (border,
921 color,
922 orientation));
923 dao_set_style (dao, col1, row1, col2, row2, mstyle);
924 }
925
926
927
928 /**
929 * dao_get_colrow_state_list:
930 * @dao:
931 * @is_cols: %TRUE for columns, %FALSE for rows.
932 *
933 *
934 * Returns: (transfer full):
935 **/
936 ColRowStateList *
dao_get_colrow_state_list(data_analysis_output_t * dao,gboolean is_cols)937 dao_get_colrow_state_list (data_analysis_output_t *dao, gboolean is_cols)
938 {
939 switch (dao->type) {
940 case NewSheetOutput:
941 case NewWorkbookOutput:
942 return NULL;
943 case RangeOutput:
944 if (is_cols)
945 return colrow_get_states
946 (dao->sheet, is_cols, dao->start_col,
947 dao->start_col + dao->cols - 1);
948 else
949 return colrow_get_states
950 (dao->sheet, is_cols, dao->start_row,
951 dao->start_row + dao->rows - 1);
952 default:
953 return NULL;
954 }
955 }
956
957 /**
958 * dao_set_colrow_state_list:
959 * @dao:
960 * @is_cols: %TRUE for columns, %FALSE for rows.
961 * @list:
962 *
963 **/
964 void
dao_set_colrow_state_list(data_analysis_output_t * dao,gboolean is_cols,ColRowStateList * list)965 dao_set_colrow_state_list (data_analysis_output_t *dao, gboolean is_cols,
966 ColRowStateList *list)
967 {
968 g_return_if_fail (list);
969
970 if (dao->type == RangeOutput)
971 colrow_set_states (dao->sheet, is_cols,
972 is_cols ? dao->start_col : dao->start_row,
973 list);
974 }
975
976 void
dao_append_date(GString * buf)977 dao_append_date (GString *buf)
978 {
979 GDate date;
980 struct tm tm_s;
981 gchar *tmp;
982 time_t now;
983
984 now = time (NULL);
985 g_date_set_time_t (&date, now);
986 g_date_to_struct_tm (&date, &tm_s);
987 tm_s.tm_sec = now % 60;
988 tm_s.tm_min = (now / 60) % 60;
989 tm_s.tm_hour = (now / 3600) % 24;
990 tmp = asctime (&tm_s);
991 g_string_append (buf, tmp);
992 }
993
994 /**
995 * dao_write_header:
996 * @dao:
997 * @toolname: name of the tool, like Solver or Risk simulation
998 * @title:
999 * @sheet:
1000 *
1001 * Writes the titles of a report.
1002 *
1003 **/
1004 void
dao_write_header(data_analysis_output_t * dao,const gchar * toolname,const gchar * title,Sheet * sheet)1005 dao_write_header (data_analysis_output_t *dao, const gchar *toolname,
1006 const gchar *title, Sheet *sheet)
1007 {
1008 GString *buf;
1009 const char *uri;
1010
1011 buf = g_string_new (NULL);
1012 g_string_append_printf (buf, "%s %s %s %s",
1013 _("Gnumeric "), toolname, VERSION, title);
1014 dao_set_cell (dao, 0, 0, buf->str);
1015 g_string_free (buf, FALSE);
1016
1017 buf = g_string_new (NULL);
1018 uri = go_doc_get_uri (GO_DOC (sheet->workbook));
1019 g_string_append_printf (buf, "%s [%s]%s", _("Worksheet:"),
1020 uri,
1021 sheet->name_quoted);
1022 dao_set_cell (dao, 0, 1, buf->str);
1023 g_string_free (buf, FALSE);
1024
1025 buf = g_string_new (NULL);
1026 g_string_append (buf, _("Report Created: "));
1027 dao_append_date (buf);
1028 dao_set_cell (dao, 0, 2, buf->str);
1029 g_string_free (buf, FALSE);
1030
1031 dao_set_bold (dao, 0, 0, 0, 2);
1032 }
1033
1034
1035 char *
dao_find_name(Sheet * sheet,int col,int row)1036 dao_find_name (Sheet *sheet, int col, int row)
1037 {
1038 static char *str = NULL;
1039 const char *col_str = "";
1040 const char *row_str = "";
1041 int col_n, row_n;
1042
1043 for (col_n = col - 1; col_n >= 0; col_n--) {
1044 GnmCell *cell = sheet_cell_get (sheet, col_n, row);
1045 if (cell && !VALUE_IS_NUMBER (cell->value)) {
1046 col_str = value_peek_string (cell->value);
1047 break;
1048 }
1049 }
1050
1051 for (row_n = row - 1; row_n >= 0; row_n--) {
1052 GnmCell *cell = sheet_cell_get (sheet, col, row_n);
1053 if (cell && !VALUE_IS_NUMBER (cell->value)) {
1054 row_str = value_peek_string (cell->value);
1055 break;
1056 }
1057 }
1058
1059 if (*col_str || *row_str) {
1060 str = g_new (char, strlen (col_str) + strlen (row_str) + 2);
1061
1062 if (*col_str)
1063 sprintf (str, "%s %s", col_str, row_str);
1064 else
1065 sprintf (str, "%s", row_str);
1066 } else {
1067 const char *tmp = cell_coord_name (col, row);
1068
1069 str = g_new (char, strlen (tmp) + 1);
1070 strcpy (str, tmp);
1071 }
1072
1073 return str;
1074 }
1075
1076 gboolean
dao_put_formulas(data_analysis_output_t * dao)1077 dao_put_formulas (data_analysis_output_t *dao)
1078 {
1079 g_return_val_if_fail (dao != NULL, FALSE);
1080 return dao->put_formulas;
1081 }
1082
1083 static GnmValue *
cb_convert_to_value(GnmCellIter const * iter,G_GNUC_UNUSED gpointer user)1084 cb_convert_to_value (GnmCellIter const *iter, G_GNUC_UNUSED gpointer user)
1085 {
1086 GnmCell *cell = iter->cell;
1087 if (!cell || !gnm_cell_has_expr (cell))
1088 return NULL;
1089
1090 gnm_cell_eval (cell);
1091
1092 if (gnm_expr_top_is_array_elem (cell->base.texpr, NULL, NULL))
1093 return NULL;
1094
1095 gnm_cell_convert_expr_to_value (cell);
1096 return NULL;
1097 }
1098
1099
1100 static void
dao_convert_to_values(data_analysis_output_t * dao)1101 dao_convert_to_values (data_analysis_output_t *dao)
1102 {
1103 if (dao->put_formulas)
1104 return;
1105
1106 sheet_foreach_cell_in_region (dao->sheet, CELL_ITER_IGNORE_BLANK,
1107 dao->start_col, dao->start_row,
1108 dao->start_col + dao->cols - 1,
1109 dao->start_row + dao->rows - 1,
1110 cb_convert_to_value,
1111 NULL);
1112 }
1113
1114 void
dao_redraw_respan(data_analysis_output_t * dao)1115 dao_redraw_respan (data_analysis_output_t *dao)
1116 {
1117 GnmRange r;
1118
1119 range_init (&r, dao->start_col, dao->start_row,
1120 dao->start_col + dao->cols - 1,
1121 dao->start_row + dao->rows - 1);
1122 sheet_range_calc_spans (dao->sheet, &r,
1123 GNM_SPANCALC_RESIZE | GNM_SPANCALC_RE_RENDER);
1124 sheet_region_queue_recalc (dao->sheet, &r);
1125 dao_convert_to_values (dao);
1126 sheet_redraw_range (dao->sheet, &r);
1127 }
1128
1129
1130 static GnmExpr const *
dao_get_cellref_full(data_analysis_output_t * dao,int x,int y,Sheet * sheet)1131 dao_get_cellref_full (data_analysis_output_t *dao, int x, int y, Sheet *sheet)
1132 {
1133 GnmCellRef r;
1134 r.sheet = sheet;
1135 r.col = x + dao->start_col + dao->offset_col;
1136 r.col_relative = FALSE;
1137 r.row = y + dao->start_row + dao->offset_row;
1138 r.row_relative = FALSE;
1139 return gnm_expr_new_cellref (&r);
1140 }
1141
1142 GnmExpr const *
dao_get_cellref(data_analysis_output_t * dao,int x,int y)1143 dao_get_cellref (data_analysis_output_t *dao, int x, int y)
1144 {
1145 return dao_get_cellref_full (dao, x, y, NULL);
1146 }
1147
1148 static GnmExpr const *
dao_get_rangeref_full(data_analysis_output_t * dao,int ax,int ay,int bx,int by,Sheet * sheet)1149 dao_get_rangeref_full (data_analysis_output_t *dao, int ax, int ay, int bx, int by, Sheet *sheet)
1150 {
1151 GnmValue *v;
1152 GnmCellRef ar;
1153 GnmCellRef br;
1154
1155 ar.sheet = sheet;
1156 ar.col = ax + dao->start_col + dao->offset_col;
1157 ar.col_relative = FALSE;
1158 ar.row = ay + dao->start_row + dao->offset_row;
1159 ar.row_relative = FALSE;
1160
1161 br.sheet = sheet;
1162 br.col = bx + dao->start_col + dao->offset_col;
1163 br.col_relative = FALSE;
1164 br.row = by + dao->start_row + dao->offset_row;
1165 br.row_relative = FALSE;
1166
1167 v = value_new_cellrange (&ar, &br, 0, 0);
1168 return gnm_expr_new_constant (v);
1169 }
1170
1171 GnmExpr const *
dao_get_rangeref(data_analysis_output_t * dao,int ax,int ay,int bx,int by)1172 dao_get_rangeref (data_analysis_output_t *dao, int ax, int ay, int bx, int by)
1173 {
1174 return dao_get_rangeref_full (dao, ax, ay, bx, by, NULL);
1175 }
1176
1177 void
dao_set_sheet_object(data_analysis_output_t * dao,int col,int row,SheetObject * so)1178 dao_set_sheet_object (data_analysis_output_t *dao, int col, int row, SheetObject* so)
1179 {
1180 SheetObjectAnchor anchor;
1181 GnmRange anchor_r;
1182
1183 g_return_if_fail (so != NULL);
1184
1185 if (dao->omit_so) {
1186 g_object_unref (so);
1187 return;
1188 }
1189
1190 range_init (&anchor_r, dao->start_col + col, dao->start_row + row,
1191 dao->start_col + ((dao->cols < 5) ? dao->cols : 5),
1192 dao->start_row + ((dao->rows < 20) ? dao->rows : 20));
1193
1194 sheet_object_anchor_init (&anchor, &anchor_r, NULL, GOD_ANCHOR_DIR_UNKNOWN,
1195 GNM_SO_ANCHOR_TWO_CELLS);
1196 sheet_object_set_anchor (so, &anchor);
1197 sheet_object_set_sheet (so, dao->sheet);
1198
1199 dao->sos = g_slist_prepend (dao->sos, so);
1200 }
1201
1202 /**
1203 * dao_go_data_vector:
1204 * @dao:
1205 * @ax:
1206 * @ay:
1207 * @bx:
1208 * @by:
1209 *
1210 * Returns: (transfer full):
1211 **/
1212 GOData *
dao_go_data_vector(data_analysis_output_t * dao,int ax,int ay,int bx,int by)1213 dao_go_data_vector (data_analysis_output_t *dao, int ax, int ay, int bx, int by)
1214 {
1215 return gnm_go_data_vector_new_expr (dao->sheet, gnm_expr_top_new (dao_get_rangeref_full (dao, ax, ay, bx, by, dao->sheet)));
1216 }
1217
1218 /**
1219 * dao_surrender_so:
1220 * @dao:
1221 *
1222 * Returns: (element-type GObject) (transfer full):
1223 **/
1224 GSList *
dao_surrender_so(data_analysis_output_t * dao)1225 dao_surrender_so (data_analysis_output_t *dao)
1226 {
1227 GSList *l = dao->sos;
1228 dao->sos = NULL;
1229
1230 return l;
1231 }
1232
1233 void
dao_set_omit_so(data_analysis_output_t * dao,gboolean omit)1234 dao_set_omit_so (data_analysis_output_t *dao, gboolean omit)
1235 {
1236 dao->omit_so = omit;
1237 }
1238
1239
1240
1241 void
dao_set_merge(data_analysis_output_t * dao,int col1,int row1,int col2,int row2)1242 dao_set_merge (data_analysis_output_t *dao, int col1, int row1,
1243 int col2, int row2)
1244 {
1245 GnmRange r;
1246
1247 range_init (&r, col1, row1, col2, row2);
1248 if (adjust_range (dao, &r))
1249 gnm_sheet_merge_add (dao->sheet, &r, TRUE, NULL);
1250 }
1251