1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
7 * Jukka-Pekka Iivonen <jiivonen@hutcs.cs.hut.fi>
9 * (C) Copyright 2000, 2001, 2002 by Jukka-Pekka Iivonen <iivonen@iki.fi>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses/>.
25 #include <gnumeric-config.h>
26 #include <glib/gi18n-lib.h>
30 #include <sheet-filter.h>
31 #include <workbook-control.h>
35 #include <selection.h>
39 #include "analysis-tools.h"
42 filter (data_analysis_output_t
*dao
, Sheet
*sheet
, GSList
*rows
,
43 gint input_col_b
, gint input_col_e
, gint input_row_b
, gint input_row_e
)
48 if (dao
->type
== InPlaceOutput
) {
49 sheet
->has_filtered_rows
= TRUE
;
50 colrow_set_visibility (sheet
, FALSE
,
51 FALSE
, input_row_b
+1, input_row_e
);
52 for (i
=input_row_b
; i
<=input_row_e
; i
++) {
53 ColRowInfo
*ri
= sheet_row_fetch (sheet
, i
);
54 ri
->in_advanced_filter
= TRUE
;
56 while (rows
!= NULL
) {
57 const gint
*row
= rows
->data
;
58 colrow_set_visibility (sheet
, FALSE
, TRUE
, *row
, *row
);
61 sheet_redraw_all (sheet
, TRUE
);
62 /* FIXME: what happens if we just have hidden the selection? */
65 for (i
=input_col_b
; i
<=input_col_e
; i
++) {
66 cell
= sheet_cell_get (sheet
, i
, input_row_b
);
68 dao_set_cell (dao
, i
- input_col_b
, r
, NULL
);
70 GnmValue
*value
= value_dup (cell
->value
);
71 dao_set_cell_value (dao
, i
- input_col_b
, r
,
77 while (rows
!= NULL
) {
78 const gint
*row
= rows
->data
;
79 for (i
=input_col_b
; i
<=input_col_e
; i
++) {
80 cell
= sheet_cell_get (sheet
, i
, *row
);
82 dao_set_cell (dao
, i
- input_col_b
, r
,
86 value_dup (cell
->value
);
87 dao_set_cell_value (dao
,
99 * Advanced Filter tool.
102 advanced_filter (WorkbookControl
*wbc
,
103 data_analysis_output_t
*dao
,
106 gboolean unique_only_flag
)
112 Sheet
*sheet
= criteria
->v_range
.cell
.a
.sheet
;
114 /* I don't like this -- minimal fix for now. 509427. */
115 if (!VALUE_IS_CELLRANGE (criteria
))
116 return analysis_tools_invalid_field
;
118 crit
= parse_database_criteria (
119 eval_pos_init_sheet (&ep
, wb_control_cur_sheet (wbc
)),
123 return analysis_tools_invalid_field
;
125 rows
= find_rows_that_match (sheet
,
126 database
->v_range
.cell
.a
.col
,
127 database
->v_range
.cell
.a
.row
+ 1,
128 database
->v_range
.cell
.b
.col
,
129 database
->v_range
.cell
.b
.row
,
130 crit
, unique_only_flag
);
132 free_criterias (crit
);
135 return analysis_tools_no_records_found
;
137 dao_prepare_output (wbc
, dao
, _("Filtered"));
139 filter (dao
, sheet
, rows
,
140 database
->v_range
.cell
.a
.col
,
141 database
->v_range
.cell
.b
.col
, database
->v_range
.cell
.a
.row
,
142 database
->v_range
.cell
.b
.row
);
144 g_slist_free_full (rows
, (GDestroyNotify
)g_free
);
146 sv
= sheet_get_view (sheet
, wb_control_view (wbc
));
147 s
= r
= *(selection_first_range (sv
, NULL
, NULL
));
148 r
.end
.row
= r
.start
.row
;
149 sv_selection_reset (sv
);
150 sv_selection_add_range (sv
, &r
);
151 sv_selection_add_range (sv
, &s
);
153 wb_control_menu_state_update (wbc
, MS_FILTER_STATE_CHANGED
);
155 return analysis_tools_noerr
;
159 cb_show_all (GnmColRowIter
const *iter
, Sheet
*sheet
)
161 if (iter
->cri
->in_advanced_filter
) {
162 ColRowInfo
*ri
= sheet_row_fetch (sheet
, iter
->pos
);
163 if (!iter
->cri
->visible
)
164 colrow_set_visibility (sheet
, FALSE
, TRUE
,
165 iter
->pos
, iter
->pos
);
166 ri
->in_advanced_filter
= FALSE
;
172 filter_show_all (WorkbookControl
*wbc
)
174 Sheet
*sheet
= wb_control_cur_sheet (wbc
);
176 /* FIXME: This is slow. We should probably have a linked list
177 * containing the filtered rows in the sheet structure. */
178 sheet_colrow_foreach (sheet
, FALSE
, 0, -1,
179 (ColRowHandler
) cb_show_all
, sheet
);
180 sheet
->has_filtered_rows
= FALSE
;
181 sheet_redraw_all (sheet
, TRUE
);
183 wb_control_menu_state_update (wbc
, MS_FILTER_STATE_CHANGED
);
187 analysis_tool_advanced_filter_engine_run (data_analysis_output_t
*dao
,
188 analysis_tools_data_advanced_filter_t
*info
)
192 GnmValue
*database
= info
->base
.range_1
;
193 GnmValue
*criteria
= info
->base
.range_2
;
194 gint err
= analysis_tools_noerr
;
198 dao_set_italic (dao
, 0, 0, 0, 2);
199 set_cell_text_col (dao
, 0, 0, _("/Advanced Filter:"
201 "/Criteria Range:"));
202 range_init_value (&range
, database
);
203 name
= global_range_name (database
->v_range
.cell
.a
.sheet
, &range
);
204 dao_set_cell (dao
, 1, 1, name
);
206 range_init_value (&range
, criteria
);
207 name
= global_range_name (criteria
->v_range
.cell
.a
.sheet
, &range
);
208 dao_set_cell (dao
, 1, 2, name
);
213 crit
= parse_database_criteria (
214 eval_pos_init_sheet (&ep
, wb_control_cur_sheet (info
->base
.wbc
)),
218 err
= analysis_tools_invalid_field
;
222 rows
= find_rows_that_match (database
->v_range
.cell
.a
.sheet
,
223 database
->v_range
.cell
.a
.col
,
224 database
->v_range
.cell
.a
.row
+ 1,
225 database
->v_range
.cell
.b
.col
,
226 database
->v_range
.cell
.b
.row
,
227 crit
, info
->unique_only_flag
);
229 free_criterias (crit
);
232 err
= analysis_tools_no_records_found
;
236 filter (dao
, database
->v_range
.cell
.a
.sheet
, rows
,
237 database
->v_range
.cell
.a
.col
,
238 database
->v_range
.cell
.b
.col
, database
->v_range
.cell
.a
.row
,
239 database
->v_range
.cell
.b
.row
);
241 g_slist_free_full (rows
, (GDestroyNotify
)g_free
);
244 if (err
!= analysis_tools_noerr
) {
245 dao_set_merge (dao
, 0,0, 1, 0);
246 if (err
== analysis_tools_no_records_found
)
247 dao_set_cell (dao
, 0, 0, _("No matching records were found."));
248 else if (err
== analysis_tools_invalid_field
)
249 dao_set_cell (dao
, 0, 0, _("The given criteria are invalid."));
251 dao_set_cell_printf (dao
, 0, 0,
252 _("An unexpected error has occurred: "
256 dao_redraw_respan (dao
);
258 return analysis_tools_noerr
;
263 analysis_tool_advanced_filter_engine (G_GNUC_UNUSED GOCmdContext
*gcc
, data_analysis_output_t
*dao
, gpointer specs
,
264 analysis_tool_engine_t selector
, gpointer result
)
266 analysis_tools_data_advanced_filter_t
*info
= specs
;
268 case TOOL_ENGINE_UPDATE_DESCRIPTOR
:
269 return (dao_command_descriptor (dao
, _("Advanced Filter (%s)"), result
)
271 case TOOL_ENGINE_UPDATE_DAO
: {
273 rows
= info
->base
.range_1
->v_range
.cell
.b
.row
274 - info
->base
.range_1
->v_range
.cell
.a
.row
+ 1;
275 cols
= info
->base
.range_1
->v_range
.cell
.b
.col
276 - info
->base
.range_1
->v_range
.cell
.a
.col
+ 1;
279 dao_adjust (dao
, cols
, 3 + rows
);
282 case TOOL_ENGINE_CLEAN_UP
:
283 return analysis_tool_generic_b_clean (specs
);
284 case TOOL_ENGINE_LAST_VALIDITY_CHECK
:
286 case TOOL_ENGINE_PREPARE_OUTPUT_RANGE
:
287 dao_prepare_output (NULL
, dao
, _("Advanced Filter"));
289 case TOOL_ENGINE_FORMAT_OUTPUT_RANGE
:
290 return dao_format_output (dao
, _("Advanced Filter"));
291 case TOOL_ENGINE_PERFORM_CALC
:
293 return analysis_tool_advanced_filter_engine_run (dao
, info
);
295 return TRUE
; /* We shouldn't get here */