Update Spanish translation
[gnumeric.git] / src / tools / filter.c
blob34137d4a8b6443680e081c2b3c019ca99e1946c9
2 /*
3 * filter.c:
5 * Author:
6 * Jukka-Pekka Iivonen <jiivonen@hutcs.cs.hut.fi>
8 * (C) Copyright 2000, 2001, 2002 by Jukka-Pekka Iivonen <iivonen@iki.fi>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <https://www.gnu.org/licenses/>.
24 #include <gnumeric-config.h>
25 #include <glib/gi18n-lib.h>
26 #include <gnumeric.h>
28 #include <sheet.h>
29 #include <sheet-filter.h>
30 #include <workbook-control.h>
31 #include <cell.h>
32 #include <ranges.h>
33 #include <value.h>
34 #include <selection.h>
35 #include <criteria.h>
37 #include <tools/filter.h>
38 #include <tools/analysis-tools.h>
40 static void
41 filter (data_analysis_output_t *dao, Sheet *sheet, GSList *rows,
42 gint input_col_b, gint input_col_e, gint input_row_b, gint input_row_e)
44 GnmCell *cell;
45 int i, r=0;
47 if (dao->type == InPlaceOutput) {
48 sheet->has_filtered_rows = TRUE;
49 colrow_set_visibility (sheet, FALSE,
50 FALSE, input_row_b+1, input_row_e);
51 for (i=input_row_b; i<=input_row_e; i++) {
52 ColRowInfo *ri = sheet_row_fetch (sheet, i);
53 ri->in_advanced_filter = TRUE;
55 while (rows != NULL) {
56 gint row = GPOINTER_TO_INT (rows->data);
57 colrow_set_visibility (sheet, FALSE, TRUE, row, row);
58 rows = rows->next;
60 sheet_redraw_all (sheet, TRUE);
61 /* FIXME: what happens if we just have hidden the selection? */
63 } else {
64 for (i=input_col_b; i<=input_col_e; i++) {
65 cell = sheet_cell_get (sheet, i, input_row_b);
66 if (cell == NULL)
67 dao_set_cell (dao, i - input_col_b, r, NULL);
68 else {
69 GnmValue *value = value_dup (cell->value);
70 dao_set_cell_value (dao, i - input_col_b, r,
71 value);
74 ++r;
76 while (rows != NULL) {
77 gint row = GPOINTER_TO_INT (rows->data);
78 for (i=input_col_b; i<=input_col_e; i++) {
79 cell = sheet_cell_get (sheet, i, row);
80 if (cell == NULL)
81 dao_set_cell (dao, i - input_col_b, r,
82 NULL);
83 else {
84 GnmValue *value =
85 value_dup (cell->value);
86 dao_set_cell_value (dao,
87 i - input_col_b, r,
88 value);
91 ++r;
92 rows = rows->next;
98 * Advanced Filter tool.
100 gint
101 advanced_filter (WorkbookControl *wbc,
102 data_analysis_output_t *dao,
103 GnmValue *database,
104 GnmValue *criteria,
105 gboolean unique_only_flag)
107 GSList *crit, *rows;
108 GnmEvalPos ep;
109 GnmRange r, s;
110 SheetView *sv;
111 Sheet *sheet = criteria->v_range.cell.a.sheet;
113 /* I don't like this -- minimal fix for now. 509427. */
114 if (!VALUE_IS_CELLRANGE (criteria))
115 return analysis_tools_invalid_field;
117 crit = parse_database_criteria (
118 eval_pos_init_sheet (&ep, wb_control_cur_sheet (wbc)),
119 database, criteria);
121 if (crit == NULL)
122 return analysis_tools_invalid_field;
124 rows = find_rows_that_match (sheet,
125 database->v_range.cell.a.col,
126 database->v_range.cell.a.row + 1,
127 database->v_range.cell.b.col,
128 database->v_range.cell.b.row,
129 crit, unique_only_flag);
131 free_criterias (crit);
133 if (rows == NULL)
134 return analysis_tools_no_records_found;
136 dao_prepare_output (wbc, dao, _("Filtered"));
138 filter (dao, sheet, rows,
139 database->v_range.cell.a.col,
140 database->v_range.cell.b.col, database->v_range.cell.a.row,
141 database->v_range.cell.b.row);
143 sv = sheet_get_view (sheet, wb_control_view (wbc));
144 s = r = *(selection_first_range (sv, NULL, NULL));
145 r.end.row = r.start.row;
146 sv_selection_reset (sv);
147 sv_selection_add_range (sv, &r);
148 sv_selection_add_range (sv, &s);
150 wb_control_menu_state_update (wbc, MS_FILTER_STATE_CHANGED);
152 return analysis_tools_noerr;
155 static gboolean
156 cb_show_all (GnmColRowIter const *iter, Sheet *sheet)
158 if (iter->cri->in_advanced_filter) {
159 ColRowInfo *ri = sheet_row_fetch (sheet, iter->pos);
160 if (!iter->cri->visible)
161 colrow_set_visibility (sheet, FALSE, TRUE,
162 iter->pos, iter->pos);
163 ri->in_advanced_filter = FALSE;
165 return FALSE;
168 void
169 filter_show_all (WorkbookControl *wbc)
171 Sheet *sheet = wb_control_cur_sheet (wbc);
173 /* FIXME: This is slow. We should probably have a linked list
174 * containing the filtered rows in the sheet structure. */
175 sheet_colrow_foreach (sheet, FALSE, 0, -1,
176 (ColRowHandler) cb_show_all, sheet);
177 sheet->has_filtered_rows = FALSE;
178 sheet_redraw_all (sheet, TRUE);
180 wb_control_menu_state_update (wbc, MS_FILTER_STATE_CHANGED);
183 static gboolean
184 analysis_tool_advanced_filter_engine_run (data_analysis_output_t *dao,
185 analysis_tools_data_advanced_filter_t *info)
187 GnmRange range;
188 char *name;
189 GnmValue *database = info->base.range_1;
190 GnmValue *criteria = info->base.range_2;
191 gint err = analysis_tools_noerr;
192 GSList *crit, *rows;
193 GnmEvalPos ep;
195 dao_set_italic (dao, 0, 0, 0, 2);
196 set_cell_text_col (dao, 0, 0, _("/Advanced Filter:"
197 "/Source Range:"
198 "/Criteria Range:"));
199 range_init_value (&range, database);
200 name = global_range_name (database->v_range.cell.a.sheet, &range);
201 dao_set_cell (dao, 1, 1, name);
202 g_free (name);
203 range_init_value (&range, criteria);
204 name = global_range_name (criteria->v_range.cell.a.sheet, &range);
205 dao_set_cell (dao, 1, 2, name);
206 g_free (name);
208 dao->offset_row = 3;
210 crit = parse_database_criteria (
211 eval_pos_init_sheet (&ep, wb_control_cur_sheet (info->base.wbc)),
212 database, criteria);
214 if (crit == NULL) {
215 err = analysis_tools_invalid_field;
216 goto finish;
219 rows = find_rows_that_match (database->v_range.cell.a.sheet,
220 database->v_range.cell.a.col,
221 database->v_range.cell.a.row + 1,
222 database->v_range.cell.b.col,
223 database->v_range.cell.b.row,
224 crit, info->unique_only_flag);
226 free_criterias (crit);
228 if (rows == NULL) {
229 err = analysis_tools_no_records_found;
230 goto finish;
233 filter (dao, database->v_range.cell.a.sheet, rows,
234 database->v_range.cell.a.col,
235 database->v_range.cell.b.col, database->v_range.cell.a.row,
236 database->v_range.cell.b.row);
238 finish:
239 if (err != analysis_tools_noerr) {
240 dao_set_merge (dao, 0,0, 1, 0);
241 if (err == analysis_tools_no_records_found)
242 dao_set_cell (dao, 0, 0, _("No matching records were found."));
243 else if (err == analysis_tools_invalid_field)
244 dao_set_cell (dao, 0, 0, _("The given criteria are invalid."));
245 else
246 dao_set_cell_printf (dao, 0, 0,
247 _("An unexpected error has occurred: "
248 "%d."), err);
251 dao_redraw_respan (dao);
253 return analysis_tools_noerr;
257 gboolean
258 analysis_tool_advanced_filter_engine (G_GNUC_UNUSED GOCmdContext *gcc, data_analysis_output_t *dao, gpointer specs,
259 analysis_tool_engine_t selector, gpointer result)
261 analysis_tools_data_advanced_filter_t *info = specs;
262 switch (selector) {
263 case TOOL_ENGINE_UPDATE_DESCRIPTOR:
264 return (dao_command_descriptor (dao, _("Advanced Filter (%s)"), result)
265 == NULL);
266 case TOOL_ENGINE_UPDATE_DAO: {
267 int rows, cols;
268 rows = info->base.range_1->v_range.cell.b.row
269 - info->base.range_1->v_range.cell.a.row + 1;
270 cols = info->base.range_1->v_range.cell.b.col
271 - info->base.range_1->v_range.cell.a.col + 1;
272 if (cols < 2)
273 cols = 2;
274 dao_adjust (dao, cols, 3 + rows);
275 return FALSE;
277 case TOOL_ENGINE_CLEAN_UP:
278 return analysis_tool_generic_b_clean (specs);
279 case TOOL_ENGINE_LAST_VALIDITY_CHECK:
280 return FALSE;
281 case TOOL_ENGINE_PREPARE_OUTPUT_RANGE:
282 dao_prepare_output (NULL, dao, _("Advanced Filter"));
283 return FALSE;
284 case TOOL_ENGINE_FORMAT_OUTPUT_RANGE:
285 return dao_format_output (dao, _("Advanced Filter"));
286 case TOOL_ENGINE_PERFORM_CALC:
287 default:
288 return analysis_tool_advanced_filter_engine_run (dao, info);
290 return TRUE; /* We shouldn't get here */