3 * value-sheet.c: Utilies for sheet specific value handling
6 * Miguel de Icaza (miguel@gnu.org).
8 #include <gnumeric-config.h>
9 #include <glib/gi18n-lib.h>
13 #include <gnm-format.h>
18 #include <parse-util.h>
19 #include <goffice/goffice.h>
21 /* Debugging utility to print a GnmValue */
23 value_dump (GnmValue
const *value
)
25 switch (value
->v_any
.type
){
31 g_print ("ERROR: %s\n", value
->v_err
.mesg
->str
);
35 g_print ("BOOLEAN: %s\n", go_locale_boolean_name (value
->v_bool
.val
));
39 g_print ("STRING: %s\n", value
->v_str
.val
->str
);
43 g_print ("NUMBER: %" GNM_FORMAT_f
"\n", value_get_as_float (value
));
49 g_print ("Array: { ");
50 for (y
= 0; y
< value
->v_array
.y
; y
++)
51 for (x
= 0; x
< value
->v_array
.x
; x
++)
52 value_dump (value
->v_array
.vals
[x
][y
]);
56 case VALUE_CELLRANGE
: {
58 * Do NOT normalize the ranges.
59 * Lets see them in their inverted glory if need be.
61 GnmCellRef
const *c
= &value
->v_range
.cell
.a
;
62 Sheet
const *sheet
= c
->sheet
;
64 g_print ("CellRange\n");
65 if (sheet
&& sheet
->name_unquoted
)
66 g_print ("%s:", sheet
->name_quoted
);
68 g_print ("%p :", (void *)sheet
);
69 g_print ("%s%s%s%s\n",
70 (c
->col_relative
? "":"$"), col_name(c
->col
),
71 (c
->row_relative
? "":"$"), row_name(c
->row
));
72 c
= &value
->v_range
.cell
.b
;
73 if (sheet
&& sheet
->name_quoted
)
74 g_print ("%s:", sheet
->name_unquoted
);
76 g_print ("%p :", (void *)sheet
);
77 g_print ("%s%s%s%s\n",
78 (c
->col_relative
? "":"$"), col_name(c
->col
),
79 (c
->row_relative
? "":"$"), row_name(c
->row
));
83 g_print ("Unhandled item type\n");
88 value_area_get_width (GnmValue
const *v
, GnmEvalPos
const *ep
)
90 g_return_val_if_fail (v
, 0);
92 if (VALUE_IS_CELLRANGE (v
)) {
94 Sheet
*start_sheet
, *end_sheet
;
96 g_return_val_if_fail (ep
, 0);
97 gnm_rangeref_normalize (&v
->v_range
.cell
, ep
, &start_sheet
, &end_sheet
, &r
);
98 return range_width (&r
);
99 } else if (VALUE_IS_ARRAY (v
))
105 value_area_get_height (GnmValue
const *v
, GnmEvalPos
const *ep
)
107 g_return_val_if_fail (v
, 0);
109 if (VALUE_IS_CELLRANGE (v
)) {
111 Sheet
*start_sheet
, *end_sheet
;
113 g_return_val_if_fail (ep
, 0);
114 gnm_rangeref_normalize (&v
->v_range
.cell
, ep
, &start_sheet
, &end_sheet
, &r
);
115 return range_height (&r
);
116 } else if (VALUE_IS_ARRAY (v
))
122 * value_area_fetch_x_y:
123 * @v: const #GnmValue *
126 * @ep: const #GnmEvalPos *
128 * An internal routine to get a cell from an array or range.
129 * Ensures that elements of CELLRANGE are evaluated
131 * Returns the element if it exists and is non-empty otherwise returns 0
134 value_area_fetch_x_y (GnmValue
const *v
, int x
, int y
, GnmEvalPos
const *ep
)
136 GnmValue
const * const res
= value_area_get_x_y (v
, x
, y
, ep
);
137 if (VALUE_IS_EMPTY (res
))
144 * value_area_get_x_y:
145 * @v: const #GnmValue *
148 * @ep: const #GnmEvalPos *
150 * An internal routine to get a cell from an array or range.
151 * Ensures that elements of CELLRANGE are evaluated
153 * If any problems occur a NULL is returned.
156 value_area_get_x_y (GnmValue
const *v
, int x
, int y
, GnmEvalPos
const *ep
)
158 g_return_val_if_fail (v
, NULL
);
160 if (VALUE_IS_ARRAY (v
)){
161 g_return_val_if_fail (x
< v
->v_array
.x
&&
164 return v
->v_array
.vals
[x
][y
];
165 } else if (VALUE_IS_CELLRANGE (v
)) {
167 Sheet
*start_sheet
, *end_sheet
;
170 gnm_rangeref_normalize (&v
->v_range
.cell
, ep
,
171 &start_sheet
, &end_sheet
,
173 if (start_sheet
!= end_sheet
)
177 x
= (r
.start
.col
+ x
) % gnm_sheet_get_max_cols (start_sheet
);
178 y
= (r
.start
.row
+ y
) % gnm_sheet_get_max_rows (start_sheet
);
181 if (start_sheet
->cols
.max_used
< x
||
182 start_sheet
->rows
.max_used
< y
)
183 return value_new_empty ();
185 cell
= sheet_cell_get (start_sheet
, x
, y
);
187 gnm_cell_eval (cell
);
191 return value_new_empty ();
198 GnmValueIterFunc func
;
199 int base_col
, base_row
;
204 cb_wrapper_foreach_cell_in_area (GnmCellIter
const *iter
, WrapperClosure
*wrap
)
206 if (iter
->cell
!= NULL
) {
207 gnm_cell_eval (iter
->cell
);
208 wrap
->v_iter
.v
= iter
->cell
->value
;
210 wrap
->v_iter
.v
= NULL
;
211 wrap
->v_iter
.x
= iter
->pp
.eval
.col
- wrap
->base_col
;
212 wrap
->v_iter
.y
= iter
->pp
.eval
.row
- wrap
->base_row
;
213 wrap
->v_iter
.cell_iter
= iter
;
214 return (*wrap
->func
) (&wrap
->v_iter
, wrap
->user_data
);
218 * value_area_foreach:
219 * @v: const #GnmValue
220 * @ep: const #GnmEvalPos
221 * @flags: #CellIterFlags
222 * @func: (scope call): #GnmValueIterFunc
225 * For each existing element in an array or range , invoke the
228 * Returns: (transfer none):
229 * non-NULL on error, or VALUE_TERMINATE if some invoked routine requested
230 * to stop (by returning non-NULL).
233 value_area_foreach (GnmValue
const *v
, GnmEvalPos
const *ep
,
235 GnmValueIterFunc func
,
241 g_return_val_if_fail (func
!= NULL
, NULL
);
243 if (VALUE_IS_CELLRANGE (v
)) {
246 Sheet
*start_sheet
, *end_sheet
;
248 gnm_rangeref_normalize (&v
->v_range
.cell
, ep
, &start_sheet
, &end_sheet
, &r
);
251 wrap
.v_iter
.region
= v
;
253 wrap
.user_data
= user_data
;
254 wrap
.base_col
= r
.start
.col
;
255 wrap
.base_row
= r
.start
.row
;
256 return workbook_foreach_cell_in_range (ep
, v
, flags
,
257 (CellIterFunc
) cb_wrapper_foreach_cell_in_area
, &wrap
);
262 v_iter
.cell_iter
= NULL
;
264 /* If not an array, apply func to singleton */
265 if (!VALUE_IS_ARRAY (v
)) {
266 v_iter
.x
= v_iter
.y
= 0;
268 return (*func
) (&v_iter
, user_data
);
271 for (v_iter
.x
= v
->v_array
.x
; v_iter
.x
-- > 0;)
272 for (v_iter
.y
= v
->v_array
.y
; v_iter
.y
-- > 0;) {
273 v_iter
.v
= v
->v_array
.vals
[v_iter
.x
][v_iter
.y
];
274 if ((tmp
= (*func
)(&v_iter
, user_data
)) != NULL
)