static
GnmExpr const *analysis_tool_combine_area (GnmValue *val_1, GnmValue *val_2, Workbook *wb)
{
	GnmFunc *fd_array;
	GnmExpr const *expr;

	if (val_1->type == VALUE_CELLRANGE && val_2->type == VALUE_CELLRANGE &&
	    val_1->v_range.cell.a.sheet == val_2->v_range.cell.a.sheet) {
		GnmRange r_1, r_2;
		gboolean combined = FALSE;

		range_init_rangeref (&r_1, &val_1->v_range.cell);
		range_init_rangeref (&r_2, &val_2->v_range.cell);

		if (r_1.start.row == r_2.start.row &&
		    range_height (&r_1) == range_height (&r_2)) {
			if (r_1.end.col == r_2.start.col - 1) {
				combined = TRUE;
				r_1.end.col = r_2.end.col;
			} else if (r_2.end.col == r_1.start.col - 1) {
				combined = TRUE;
				r_1.start.col = r_2.start.col;
			}
		} else if (r_1.start.col == r_2.start.col &&
			   range_width (&r_1) == range_width (&r_2)) {
			if (r_1.end.row == r_2.start.row - 1) {
				combined = TRUE;
				r_1.end.row = r_2.end.row;
			} else if (r_2.end.row == r_1.start.row - 1) {
				combined = TRUE;
				r_1.start.row = r_2.start.row;
			}
		}

		if (combined) {
			GnmValue *val = value_new_cellrange_r (val_1->v_range.cell.a.sheet, &r_1);
			return gnm_expr_new_constant (val);
		}
	}

	fd_array = gnm_func_lookup_or_add_placeholder ("ARRAY");
	gnm_func_ref (fd_array);

	expr = gnm_expr_new_funcall2 (fd_array,
				      gnm_expr_new_constant (value_dup (val_1)),
				      gnm_expr_new_constant (value_dup (val_2)));

	gnm_func_unref (fd_array);

	return expr;
}
Ejemplo n.º 2
0
static void
dialog_goto_load_selection (GotoState *state)
{
	SheetView *sv = wb_control_cur_sheet_view 
		(WORKBOOK_CONTROL (state->wbcg));
	GnmRange const *first = selection_first_range (sv, NULL, NULL);

	if (first != NULL) {
		gint rows = range_height (first);
		gint cols = range_width (first);
		GnmConventionsOut out;
		GString *str = g_string_new (NULL);
		GnmParsePos pp;
		GnmRangeRef rr;
		
		out.accum = str;
		out.pp = parse_pos_init_sheet (&pp, sv->sheet);
		out.convs = sheet_get_conventions (sv->sheet);
		gnm_cellref_init (&rr.a, NULL, first->start.col, 
				  first->start.row, TRUE);
		gnm_cellref_init (&rr.b, NULL, first->start.col, 
				  first->start.row, TRUE);
		rangeref_as_string (&out, &rr);
		gtk_entry_set_text (state->goto_text, str->str);
		gtk_editable_select_region (GTK_EDITABLE (state->goto_text),
					    0, -1);
		g_string_free (str, TRUE);
		cb_dialog_goto_update_sensitivity (NULL, state);
		gtk_spin_button_set_value (state->spin_rows, rows);
		gtk_spin_button_set_value (state->spin_cols, cols);
	} else
		cb_dialog_goto_update_sensitivity (NULL, state);

}
Ejemplo n.º 3
0
static int
gnm_sort_data_length (GnmSortData const *data)
{
	if (data->top)
		return range_height (data->range);
	else
		return range_width (data->range);
}
Ejemplo n.º 4
0
static GnmSolverResult *
gnm_lpsolve_start_solution (GnmLPSolve *lp)
{
	g_return_val_if_fail (lp->result == NULL, NULL);

	lp->result = g_object_new (GNM_SOLVER_RESULT_TYPE, NULL);
	lp->result->solution = value_new_array_empty
		(range_width (&lp->srinput.range),
		 range_height (&lp->srinput.range));

	return lp->result;
}
Ejemplo n.º 5
0
void
dialog_data_table (WBCGtk *wbcg)
{
	GnmDialogDataTable *state;
	GnmRange const	*r;
	GnmRange	 input_range;
	SheetView	*sv;
	Sheet		*sheet;

	g_return_if_fail (wbcg != NULL);

	if (wbc_gtk_get_guru (wbcg) ||
	    gnm_dialog_raise_if_exists (wbcg, DIALOG_DATA_TABLE_KEY))
		return;

	sv = wb_control_cur_sheet_view (GNM_WBC (wbcg));
	r = selection_first_range (sv, GO_CMD_CONTEXT (wbcg), _("Create Data Table"));
	if (NULL == r)
		return;
	if (range_width	(r) <= 1 || range_height (r) <= 1) {
		GError *msg = g_error_new (go_error_invalid(), 0,
			_("The selection must have more than 1 column and row to create a Data Table."));
		go_cmd_context_error (GO_CMD_CONTEXT (wbcg), msg);
		g_error_free (msg);
		return;
	}
	input_range = *r;
	input_range.start.col++;
	input_range.start.row++;
	sheet = sv_sheet (sv);
	if (sheet_range_splits_region (sheet, &input_range, NULL,
				       GO_CMD_CONTEXT (wbcg), _("Data Table")))
		return;
	if (cmd_cell_range_is_locked_effective
	    (sheet, &input_range, GNM_WBC (wbcg),
					   _("Data Table")))
		return;


	state = g_new0 (GnmDialogDataTable, 1);
	state->wbcg  = wbcg;
	state->sheet = sheet;
	state->input_range = input_range;
	if (data_table_init (state, wbcg)) {
		go_gtk_notice_dialog (wbcg_toplevel (wbcg), GTK_MESSAGE_ERROR,
			_("Could not create the Data Table definition dialog."));
		g_free (state);
	}
}
Ejemplo n.º 6
0
int
value_area_get_width (GnmValue const *v, GnmEvalPos const *ep)
{
	g_return_val_if_fail (v, 0);

	if (VALUE_IS_CELLRANGE (v)) {
		GnmRange r;
		Sheet *start_sheet, *end_sheet;

		g_return_val_if_fail (ep, 0);
		gnm_rangeref_normalize (&v->v_range.cell, ep, &start_sheet, &end_sheet, &r);
		return range_width (&r);
	} else if (VALUE_IS_ARRAY (v))
		return v->v_array.x;
	return 1;
}
Ejemplo n.º 7
0
/**
 * dialog_shuffle:
 * @wbcg:
 * @sheet:
 *
 * Show the dialog (guru).
 *
 **/
void
dialog_shuffle (WBCGtk *wbcg)
{
        ShuffleState    *state;
	WorkbookControl *wbc;
	GtkWidget *w;
	char const *type;
	GnmRange const *r;

	g_return_if_fail (wbcg != NULL);

	wbc = WORKBOOK_CONTROL (wbcg);

	/* Only pop up one copy per workbook */
	if (gnumeric_dialog_raise_if_exists (wbcg, SHUFFLE_KEY))
		return;

	state = g_new (ShuffleState, 1);

	if (dialog_tool_init (state, wbcg, wb_control_cur_sheet (wbc),
			      GNUMERIC_HELP_LINK_DATA_SHUFFLE,
			      "shuffle.ui", "Shuffling",
			      _("Could not create the Data Shuffling dialog."),
			      SHUFFLE_KEY,
			      G_CALLBACK (shuffle_ok_clicked_cb), NULL,
			      G_CALLBACK (shuffle_update_sensitivity_cb),
			      0))
		return;

	shuffle_update_sensitivity_cb (NULL, state);
	state->gdao = NULL;
	tool_load_selection ((GenericToolState *)state, FALSE);

	r = selection_first_range (state->sv, NULL, NULL);
	if (range_width (r) == 1)
		type = "shuffle_cols";
	else if (range_height (r) == 1)
		type = "shuffle_rows";
	else
		type = "shuffle_area";
	w = go_gtk_builder_get_widget (state->gui, type);
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), TRUE);

	gtk_widget_show (state->dialog);

        return;
}
Ejemplo n.º 8
0
/**
 * clipboard_copy_range:
 *
 * Entry point to the clipboard copy code
 */
GnmCellRegion *
clipboard_copy_range (Sheet *sheet, GnmRange const *r)
{
	GnmCellRegion *cr;
	GSList *merged, *ptr;
	GSList *objects;

	g_return_val_if_fail (IS_SHEET (sheet), NULL);
	g_return_val_if_fail (range_is_sane (r), NULL);

	cr = gnm_cell_region_new (sheet);
	cr->base = r->start;
	cr->cols = range_width (r);
	cr->rows = range_height (r);
	cr->col_state = colrow_get_states (sheet,
		TRUE,  r->start.col, r->end.col);
	cr->row_state = colrow_get_states (sheet,
		FALSE, r->start.row, r->end.row);

	sheet_foreach_cell_in_range ( sheet, CELL_ITER_IGNORE_NONEXISTENT,
		r->start.col, r->start.row,
		r->end.col, r->end.row,
		(CellIterFunc) cb_clipboard_prepend_cell, cr);
	objects = sheet_objects_get (sheet, r, G_TYPE_NONE);
	g_slist_foreach (objects, (GFunc)cb_dup_objects, cr);
	g_slist_free (objects);

	cr->styles = sheet_style_get_range (sheet, r);

	merged = gnm_sheet_merge_get_overlap (sheet, r);
	for (ptr = merged ; ptr != NULL ; ptr = ptr->next) {
		GnmRange *tmp = gnm_range_dup (ptr->data);
		range_translate (tmp, sheet, -r->start.col, -r->start.row);
		cr->merged = g_slist_prepend (cr->merged, tmp);
	}
	g_slist_free (merged);

	return cr;
}
Ejemplo n.º 9
0
static GnmValue *
get_single_cache_key_from_value (GnmValue const *r, GnmEvalPos const *ep)
{
	GnmValue *key;
	GnmSheetRange sr;
	GnmRangeRef const *rr;
	Sheet *end_sheet;
	int h, w;
	const int min_size = 25;

	rr = value_get_rangeref (r);
	gnm_rangeref_normalize (rr, ep, &sr.sheet, &end_sheet, &sr.range);
	if (sr.sheet != end_sheet)
		return NULL; /* 3D */

	h = range_height (&sr.range);
	w = range_width (&sr.range);
	if (h < min_size && w < min_size && h * w < min_size)
		return NULL;

	key = value_new_cellrange_r (sr.sheet, &sr.range);

	return key;
}
Ejemplo n.º 10
0
/**
 * dialog_fill_series_tool_init:
 * @state:
 *
 * Create the dialog (guru).
 *
 **/
static void
dialog_fill_series_tool_init (FillSeriesState *state)
{
	GtkWidget   *radio;
	char const  *button;
	GnmRange const *sel;
	gboolean prefer_rows = FALSE;

	sel = selection_first_range (state->base.sv, NULL, NULL);

	/* Set the sensitivity of Unit day. */
	radio = go_gtk_builder_get_widget (state->base.gui,
				      "type_date");
	g_signal_connect (G_OBJECT (radio), "clicked",
			  G_CALLBACK (cb_type_button_clicked), state);

	state->stop_entry = go_gtk_builder_get_widget (state->base.gui, "stop_entry");
	g_signal_connect_after (G_OBJECT (state->stop_entry),
		"changed",
		G_CALLBACK (cb_fill_series_update_sensitivity), state);
	state->step_entry = go_gtk_builder_get_widget (state->base.gui, "step_entry");
	g_signal_connect_after (G_OBJECT (state->step_entry),
		"changed",
		G_CALLBACK (cb_fill_series_update_sensitivity), state);
	state->start_entry = go_gtk_builder_get_widget (state->base.gui, "start_entry");
	g_signal_connect_after (G_OBJECT (state->start_entry),
		"changed",
		G_CALLBACK (cb_fill_series_update_sensitivity), state);


	state->date_steps_type  = go_gtk_builder_get_widget (state->base.gui,
							"table-date-unit");
	gtk_widget_set_sensitive (state->date_steps_type, FALSE);

	button = (sel == NULL ||
		  (prefer_rows =
		   (range_width (sel) >= range_height (sel))))
		? "series_in_rows"
		: "series_in_cols";
	radio = go_gtk_builder_get_widget (state->base.gui, button);
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE);

	if (sel != NULL) {
		GnmCell *cell_start;
		GnmCell *cell_end;

		dialog_tool_preset_to_range (&state->base);

		cell_start = sheet_cell_get (state->base.sheet,
				       sel->start.col, sel->start.row);
		if (cell_start) {
			char *content = gnm_cell_get_rendered_text (cell_start);
			if (content) {
				gtk_entry_set_text (GTK_ENTRY (state->start_entry),
						    content);
				g_free (content);
			}
		}
		cell_end = prefer_rows ?
			sheet_cell_get (state->base.sheet,
					sel->end.col, sel->start.row) :
			sheet_cell_get (state->base.sheet,
					sel->start.col, sel->end.row);
		if (cell_end) {
			char *content = gnm_cell_get_rendered_text (cell_end);
			if (content) {
				gtk_entry_set_text (GTK_ENTRY (state->stop_entry),
						    content);
				g_free (content);
			}
		}
		if (cell_start && cell_end) {
			float_to_entry (GTK_ENTRY(state->step_entry),
					(value_get_as_float(cell_end->value) -
					 value_get_as_float(cell_start->value))
					/ (prefer_rows ?
					   (sel->end.col-sel->start.col) :
					   (sel->end.row-sel->start.row)));
		}
	}

	cb_fill_series_update_sensitivity (NULL, state);
}
Ejemplo n.º 11
0
/**
 * clipboard_paste_region:
 * @cr: The GnmCellRegion to paste.
 * @pt: Where to paste the values.
 * @cc: The context for error handling.
 *
 * Pastes the supplied GnmCellRegion (@cr) into the supplied
 * GnmPasteTarget (@pt).  This operation is not undoable.  It does not auto grow
 * the destination if the target is a singleton.  This is a simple interface to
 * paste a region.
 *
 * returns : TRUE if there was a problem.
 **/
gboolean
clipboard_paste_region (GnmCellRegion const *cr,
			GnmPasteTarget const *pt,
			GOCmdContext *cc)
{
	int repeat_horizontal, repeat_vertical, clearFlags;
	int dst_cols, dst_rows, src_cols, src_rows;
	int i, j;
	GSList *ptr;
	GnmRange const *r;
	gboolean has_contents, adjust_merges = TRUE;
	struct paste_cell_data dat;
	GnmRange const *merge_src;

	g_return_val_if_fail (pt != NULL, TRUE);
	g_return_val_if_fail (cr != NULL, TRUE);

	/* we do not need any of this fancy stuff when pasting a simple object */
	if (cr->cell_content == NULL &&
	    cr->styles == NULL &&
	    cr->merged == NULL &&
	    cr->objects != NULL) {
		if (pt->paste_flags & (PASTE_COMMENTS | PASTE_OBJECTS))
			for (ptr = cr->objects; ptr; ptr = ptr->next)
				paste_object (pt, ptr->data,
					pt->range.start.col, pt->range.start.row);
		return FALSE;
	}

	r = &pt->range;
	dst_cols = range_width (r);
	dst_rows = range_height (r);
	src_cols = cr->cols;
	src_rows = cr->rows;



	/* If the source is a single cell or a single merge */
	/* Treat a target of a single merge specially, don't split the merge */
	if ((src_cols == 1 && src_rows == 1) ||
	    (g_slist_length (cr->merged) == 1 &&
	     (NULL != (merge_src = cr->merged->data)) &&
	     range_height (merge_src) == cr->rows &&
	     range_width (merge_src) == cr->cols)) {
		GnmRange const *merge = gnm_sheet_merge_is_corner (pt->sheet, &r->start);
		if (merge != NULL && range_equal (r, merge)) {
			dst_cols = dst_rows = 1;
			adjust_merges = FALSE;
			src_cols = 1;
			src_rows = 1;
		}
	/* Apparently links do not supercede merges */
	} else if (pt->paste_flags & PASTE_LINK)
		adjust_merges = FALSE;

	has_contents = pt->paste_flags & (PASTE_CONTENTS|PASTE_AS_VALUES|PASTE_LINK);

	if (pt->paste_flags & PASTE_TRANSPOSE) {
		int tmp = src_cols;
		src_cols = src_rows;
		src_rows = tmp;
	}

	if (cr->not_as_contents && (pt->paste_flags & PASTE_CONTENTS)) {
		go_cmd_context_error_invalid (cc,
					_("Unable to paste"),
					_("Contents can only be pasted by value or by link."));
		return TRUE;
	}

	/* calculate the tiling */
	repeat_horizontal = dst_cols/src_cols;
	if (repeat_horizontal * src_cols != dst_cols) {
		char *msg = g_strdup_printf (
			_("destination does not have an even multiple of source columns (%d vs %d)\n\n"
			  "Try selecting a single cell or an area of the same shape and size."),
			dst_cols, src_cols);
		go_cmd_context_error_invalid (cc, _("Unable to paste"), msg);
		g_free (msg);
		return TRUE;
	}

	repeat_vertical = dst_rows/src_rows;
	if (repeat_vertical * src_rows != dst_rows) {
		char *msg = g_strdup_printf (
			_("destination does not have an even multiple of source rows (%d vs %d)\n\n"
			  "Try selecting a single cell or an area of the same shape and size."),
			dst_rows, src_rows);
		go_cmd_context_error_invalid (cc, _("Unable to paste"), msg);
		g_free (msg);
		return TRUE;
	}

	if ((pt->range.start.col + dst_cols) > gnm_sheet_get_max_cols (pt->sheet) ||
	    (pt->range.start.row + dst_rows) > gnm_sheet_get_max_rows (pt->sheet)) {
		go_cmd_context_error_invalid (cc,
					_("Unable to paste"),
					_("result passes the sheet boundary"));
		return TRUE;
	}

	clearFlags = 0;
	/* clear the region where we will paste */
	if (has_contents)
		clearFlags = CLEAR_VALUES | CLEAR_NORESPAN;

	if (pt->paste_flags & PASTE_COMMENTS)
		clearFlags |= CLEAR_COMMENTS;

	/* No need to clear the formats.  We will paste over top of these. */
	/* if (pt->paste_flags & PASTE_FORMATS) clearFlags |= CLEAR_FORMATS; */

	if (pt->paste_flags & (PASTE_OPER_MASK | PASTE_SKIP_BLANKS))
		clearFlags = 0;

	/* remove merged regions even for operations, or blanks */
	if (has_contents && adjust_merges)
		clearFlags |= CLEAR_MERGES;

	if (clearFlags != 0) {
		int const dst_col = pt->range.start.col;
		int const dst_row = pt->range.start.row;
		sheet_clear_region (pt->sheet,
				    dst_col, dst_row,
				    dst_col + dst_cols - 1,
				    dst_row + dst_rows - 1,
				    clearFlags, cc);
	}

	dat.translate_dates = cr->date_conv &&
		!go_date_conv_equal (cr->date_conv, workbook_date_conv (pt->sheet->workbook));

	for (i = 0; i < repeat_horizontal ; i++)
		for (j = 0; j < repeat_vertical ; j++) {
			int const left = i * src_cols + pt->range.start.col;
			int const top = j * src_rows + pt->range.start.row;

			dat.top_left.col = left;
			dat.top_left.row = top;
			dat.rinfo.reloc_type = GNM_EXPR_RELOCATE_MOVE_RANGE;
			dat.rinfo.origin_sheet = dat.rinfo.target_sheet = pt->sheet;
			if (pt->paste_flags & PASTE_EXPR_LOCAL_RELOCATE) {
				dat.rinfo.origin.start = cr->base;
				dat.rinfo.origin.end.col = cr->base.col + cr->cols - 1;
				dat.rinfo.origin.end.row = cr->base.row + cr->rows - 1;
				dat.rinfo.col_offset = left - cr->base.col;
				dat.rinfo.row_offset = top - cr->base.row;
			} else {
				dat.rinfo.origin = pt->range;
				dat.rinfo.col_offset = 0;
				dat.rinfo.row_offset = 0;
			}

			/* Move the styles on here so we get correct formats before recalc */
			if (pt->paste_flags & PASTE_FORMATS) {
				if (pt->paste_flags & PASTE_TRANSPOSE)
					sheet_style_set_list (pt->sheet, &dat.top_left,
							      cr->styles,
							      (sheet_style_set_list_cb_t)
							      range_transpose,
							      &dat.top_left);
				else if (pt->paste_flags & PASTE_FLIP_H) {
					int data = 2 * left + src_cols - 1;
					sheet_style_set_list (pt->sheet, &dat.top_left,
							      cr->styles,
							      (sheet_style_set_list_cb_t)
							      range_flip_h, &data);
				} else if (pt->paste_flags & PASTE_FLIP_V) {
					int data = 2 * top + src_rows - 1;
					sheet_style_set_list (pt->sheet, &dat.top_left,
							      cr->styles,
							      (sheet_style_set_list_cb_t)
							      range_flip_v, &data);
				} else
					sheet_style_set_list (pt->sheet, &dat.top_left,
							      cr->styles, NULL, NULL);
			}
			if (has_contents && !(pt->paste_flags & PASTE_DONT_MERGE)) {
				for (ptr = cr->merged; ptr != NULL ; ptr = ptr->next) {
					GnmRange tmp = *((GnmRange const *)ptr->data);
					if (pt->paste_flags & PASTE_TRANSPOSE) {
						int x;
						x = tmp.start.col; tmp.start.col = tmp.start.row;  tmp.start.row = x;
						x = tmp.end.col; tmp.end.col = tmp.end.row;  tmp.end.row = x;
					}
					if (!range_translate (&tmp, pt->sheet, left, top))
						gnm_sheet_merge_add (pt->sheet, &tmp, TRUE, cc);
				}
			}

			if (has_contents && (pt->paste_flags & PASTE_LINK)) {
				paste_link (pt, top, left, cr);
				continue;
			}

			if (has_contents && NULL != cr->cell_content) {
				dat.pt = pt;
				dat.cr = cr;
				g_hash_table_foreach (cr->cell_content,
					(GHFunc)cb_paste_cell, &dat);
			}

			if (pt->paste_flags & (PASTE_COMMENTS | PASTE_OBJECTS))
				for (ptr = cr->objects; ptr; ptr = ptr->next)
					paste_object (pt, ptr->data, left, top);
		}

	if (!(pt->paste_flags & PASTE_NO_RECALC)) {
		if (has_contents) {
			sheet_region_queue_recalc (pt->sheet, r);
			sheet_flag_status_update_range (pt->sheet, r);
		} else
			sheet_flag_style_update_range (pt->sheet, r);

		sheet_range_calc_spans (pt->sheet, r,
					(pt->paste_flags & PASTE_FORMATS) ? GNM_SPANCALC_RE_RENDER : GNM_SPANCALC_RENDER);
		if (pt->paste_flags & PASTE_UPDATE_ROW_HEIGHT)
			rows_height_update (pt->sheet, &pt->range, FALSE);
		sheet_redraw_all (pt->sheet, FALSE);
	}

	return FALSE;
}
Ejemplo n.º 12
0
static gboolean
analysis_tool_frequency_engine_run (data_analysis_output_t *dao,
				    analysis_tools_data_frequency_t *info)
{
	gint i_limit, col;
	GSList *l;

	GnmFunc *fd_sum;
	GnmFunc *fd_if;
	GnmFunc *fd_index;
	GnmFunc *fd_isblank;
	GnmFunc *fd_rows = NULL;
	GnmFunc *fd_columns = NULL;
	GnmFunc *fd_exact = NULL;

	fd_sum = gnm_func_lookup_or_add_placeholder ("SUM");
	gnm_func_ref (fd_sum);
	fd_if = gnm_func_lookup_or_add_placeholder ("IF");
	gnm_func_ref (fd_if);
	fd_index = gnm_func_lookup_or_add_placeholder ("INDEX");
	gnm_func_ref (fd_index);
	fd_isblank = gnm_func_lookup_or_add_placeholder ("ISBLANK");
	gnm_func_ref (fd_isblank);

	if (info->exact) {
		fd_exact = gnm_func_lookup_or_add_placeholder ("EXACT");
		gnm_func_ref (fd_exact);
	}
	if (info->percentage) {
		fd_rows = gnm_func_lookup_or_add_placeholder ("ROWS");
		gnm_func_ref (fd_rows);
		fd_columns = gnm_func_lookup_or_add_placeholder ("COLUMNS");
		gnm_func_ref (fd_columns);
	}
	/* General Info */

	dao_set_italic (dao, 0, 0, 0, 1);
	set_cell_text_col (dao, 0, 0, _("/Frequency Table"
					"/Category"));

	/* Setting up the categories */

	if (info->predetermined) {
		int row = 2, i, j, i_h_limit, i_w_limit;
		GnmExpr const *expr_bin;
		GnmRange range;

		range_init_value (&range, info->bin);
		i_h_limit = range_height (&range);
		i_w_limit = range_width (&range);
		i_limit = i_h_limit * i_w_limit;

		expr_bin = gnm_expr_new_constant (info->bin);

		for (i = 1; i <= i_h_limit; i++)
			for (j = 1; j <= i_w_limit; j++) {
				GnmExpr const *expr_index;

				expr_index =  gnm_expr_new_funcall3
					(fd_index,
					 gnm_expr_copy (expr_bin),
					 gnm_expr_new_constant (value_new_int (i)),
					 gnm_expr_new_constant (value_new_int (j)));

				dao_set_cell_expr (dao, 0, row++,
						   gnm_expr_new_funcall3
						   (fd_if,
						    gnm_expr_new_funcall1
						    (fd_isblank,
						     gnm_expr_copy (expr_index)),
						    gnm_expr_new_constant (value_new_string ("")),
						    expr_index));
			}
		gnm_expr_free (expr_bin);
	} else {
		i_limit = info->n;
	}

	for (l = info->base.input, col = 1; l; col++, l = l->next) {
		GnmValue *val = value_dup ((GnmValue *)l->data);
		GnmValue *val_c = NULL;
		GnmExpr const *expr_count;
		GnmExpr const *expr_data;
		GnmExpr const *expr_if;
		int i, row = 2;


		dao_set_italic (dao, col, 1, col, 1);
		if (info->base.labels) {
			val_c = value_dup (val);
			switch (info->base.group_by) {
			case GROUPED_BY_ROW:
				val->v_range.cell.a.col++;
				break;
			default:
				val->v_range.cell.a.row++;
				break;
			}
			dao_set_cell_expr (dao, col, 1,
					   gnm_expr_new_funcall1 (fd_index,
								  gnm_expr_new_constant (val_c)));
		} else {
			char const *format;

			switch (info->base.group_by) {
			case GROUPED_BY_ROW:
				format = _("Row %d");
				break;
			case GROUPED_BY_COL:
				format = _("Column %d");
				break;
			default:
				format = _("Area %d");
				break;
			}
			dao_set_cell_printf (dao, col, 1, format, col);
		}

		expr_data = gnm_expr_new_constant (val);

		if (info->exact)
			expr_if = gnm_expr_new_funcall2
				(fd_exact, gnm_expr_copy (expr_data),
				 make_cellref (- col, 0));
		else
			expr_if = gnm_expr_new_binary
				(gnm_expr_copy (expr_data),
				 GNM_EXPR_OP_EQUAL, make_cellref (- col, 0));

		expr_count = gnm_expr_new_funcall1 (fd_sum,
						    gnm_expr_new_funcall3
						    (fd_if, expr_if,
						     gnm_expr_new_constant (value_new_int (1)),
						     gnm_expr_new_constant (value_new_int (0))));

		if (info->percentage) {
			dao_set_format  (dao, col, 2, col, i_limit + 2, "0.0%");
			expr_count = gnm_expr_new_binary (expr_count,
							  GNM_EXPR_OP_DIV,
							  gnm_expr_new_binary
							  (gnm_expr_new_funcall1
							   (fd_rows, gnm_expr_copy (expr_data)),
							   GNM_EXPR_OP_MULT,
							  gnm_expr_new_funcall1
							   (fd_columns, expr_data)));
		} else
			gnm_expr_free (expr_data);

		for (i = 0; i < i_limit; i++, row++)
			dao_set_cell_array_expr (dao, col, row, gnm_expr_copy (expr_count));

		gnm_expr_free (expr_count);
	}

	gnm_func_unref (fd_if);
	gnm_func_unref (fd_sum);
	gnm_func_unref (fd_index);
	gnm_func_unref (fd_isblank);
	if (fd_rows != NULL)
		gnm_func_unref (fd_rows);
	if (fd_columns != NULL)
		gnm_func_unref (fd_columns);
	if (fd_exact != NULL)
		gnm_func_unref (fd_exact);

	/* Create Chart if requested */
	if (info->chart != NO_CHART) {
		SheetObject *so;
		GogGraph     *graph;
		GogChart     *chart;
		GogPlot	     *plot;
		GogSeries    *series;
		GOData *cats;
		GOData *values;
		int ct;

		graph = g_object_new (GOG_TYPE_GRAPH, NULL);
		chart = GOG_CHART (gog_object_add_by_name (
						   GOG_OBJECT (graph), "Chart", NULL));
		plot = gog_plot_new_by_name ("GogBarColPlot");
		if (info->chart == BAR_CHART)
			go_object_toggle (plot, "horizontal");
		gog_object_add_by_name (GOG_OBJECT (chart),
					"Plot", GOG_OBJECT (plot));

		cats = dao_go_data_vector (dao, 0, 2,
					     0, 2 + i_limit);

		for (ct = 1; ct < col; ct ++) {
			g_object_ref (cats);
			values = dao_go_data_vector (dao, ct, 2,
						     ct, 2 + i_limit);

			series = gog_plot_new_series (plot);
			gog_series_set_dim (series, 0, cats, NULL);
			gog_series_set_dim (series, 1, values, NULL);
		}
		g_object_unref (cats);

		so = sheet_object_graph_new (graph);
		g_object_unref (graph);

		dao_set_sheet_object (dao, 0, 1, so);
	}

	dao_redraw_respan (dao);

	return FALSE;
}
Ejemplo n.º 13
0
/**
 * stf_text_to_columns:
 * @wbc: The control making the request
 * @cc:
 *
 * Main routine, handles importing a file including all dialog mumbo-jumbo
 **/
void
stf_text_to_columns (WorkbookControl *wbc, GOCmdContext *cc)
{
	DialogStfResult_t *dialogresult = NULL;
	SheetView	*sv;
	Sheet		*src_sheet, *target_sheet;
	GnmRange const	*src;
	GnmRange	 target;
	GsfOutput	*buf;
	guint8 const	*data;
	size_t data_len;

	sv    = wb_control_cur_sheet_view (wbc);
	src_sheet = sv_sheet (sv);
	src = selection_first_range (sv, cc, _("Text to Columns"));
	if (src == NULL)
		return;
	if (range_width	(src) > 1) {
		go_cmd_context_error (cc, g_error_new (go_error_invalid (), 0,
			_("Only one column of input data can be parsed at a time")));
		return;
	}

	/* FIXME : how to do this cleanly ? */
	if (!GNM_IS_WBC_GTK (wbc))
		return;

#warning Add UI for this
	target_sheet = src_sheet;
	target = *src;
	range_translate (&target, target_sheet, 1, 0);

	buf = gsf_output_memory_new ();
	sheet_foreach_cell_in_range (src_sheet,
		CELL_ITER_ALL,
		src->start.col, src->start.row,
		src->end.col, src->end.row,
		(CellIterFunc) &cb_get_content, buf);

	gsf_output_close (buf);
	data = gsf_output_memory_get_bytes (GSF_OUTPUT_MEMORY (buf));
	data_len = (size_t)gsf_output_size (buf);
	if (data_len == 0) {
		go_cmd_context_error_import (GO_CMD_CONTEXT (cc),
					     _("There is no data "
					       "to convert"));
	} else {
		dialogresult = stf_dialog (WBC_GTK (wbc),
					   NULL, FALSE, NULL, FALSE,
					   _("Text to Columns"),
					   data, data_len);
	}
	if (dialogresult != NULL) {
		GnmCellRegion *cr = stf_parse_region (dialogresult->parseoptions,
			dialogresult->text, NULL, target_sheet->workbook);
		if (cr != NULL) {
			stf_dialog_result_attach_formats_to_cr (dialogresult, cr);
			target.end.col = target.start.col + cr->cols - 1;
			target.end.row = target.start.row + cr->rows - 1;
		}
		if (cr == NULL ||
		    cmd_text_to_columns (wbc, src, src_sheet,
					 &target, target_sheet, cr))
			go_cmd_context_error_import (GO_CMD_CONTEXT (cc),
					     _("Error while trying to "
					       "parse data into sheet"));
		stf_dialog_result_free (dialogresult);
	}

	g_object_unref (buf);
}
Ejemplo n.º 14
0
/**
 * format_template_range_check:
 * @ft: Format template
 * @r: Target range
 * @optional_cc: if non-NULL display an error message if @r is not
 *			appropriate for @ft.
 *
 * Check whether range @r is big enough to apply format template @ft to it.
 *
 * Return value: TRUE if @s is big enough, FALSE if not.
 **/
static gboolean
format_template_range_check (GnmFT *ft, GnmRange const *r,
			     GOCmdContext *optional_cc)
{
	GSList *ptr;
	int diff_col_high = -1;
	int diff_row_high = -1;
	gboolean invalid_range_seen = FALSE;

	g_return_val_if_fail (ft != NULL, FALSE);

	for (ptr = ft->members; NULL != ptr ; ptr = ptr->next) {
		GnmFTMember *member = ptr->data;
		GnmRange range = gnm_ft_member_get_rect (member, r);

		if (!range_valid (&range)) {
			int diff_col = (range.start.col - range.end.col);
			int diff_row = (range.start.row - range.end.row);

			if (diff_col > diff_col_high)
				diff_col_high = diff_col;

			if (diff_row > diff_row_high)
				diff_row_high = diff_row;

			invalid_range_seen = TRUE;
		}
	}

	if (invalid_range_seen && optional_cc != NULL) {
		int diff_row_high_ft = diff_row_high + range_height (r);
		int diff_col_high_ft = diff_col_high + range_width (r);
		char *errmsg;
		char *rows, *cols;

		if (diff_col_high > 0 && diff_row_high > 0) {
			rows = g_strdup_printf (ngettext ("%d row", "%d rows", diff_row_high_ft), diff_row_high_ft);
			cols = g_strdup_printf (ngettext ("%d col", "%d cols", diff_col_high_ft), diff_col_high_ft);
			errmsg = g_strdup_printf (
				_("The target region is too small.  It should be at least %s by %s"),
				rows, cols);
			g_free (rows);
			g_free (cols);
		} else if (diff_col_high > 0)
			errmsg = g_strdup_printf (
				ngettext ("The target region is too small.  It should be at least %d column wide",
					"The target region is too small.  It should be at least %d columns wide",
					diff_col_high_ft),
				diff_col_high_ft);
		else if (diff_row_high > 0)
			errmsg = g_strdup_printf (
				ngettext ("The target region is too small.  It should be at least %d row high",
					"The target region is too small.  It should be at least %d rows high",
					diff_row_high_ft),
				diff_row_high_ft);
		else {
			errmsg = NULL;
			g_warning ("Internal error while verifying ranges! (this should not happen!)");
		}

		if (errmsg != NULL) {
			go_cmd_context_error_system (optional_cc, errmsg);
			g_free (errmsg);
		}
	}
	return !invalid_range_seen;
}