private void BenchmarkWorkbook(WorkbookForm wf, int runs, string benchmarkName, Func<long> benchmark) { Log("=== Benchmark workbook called: "); Stopwatch stopwatch = new Stopwatch(); stopwatch.Reset(); stopwatch.Start(); for (int i = 0; i < runs; i++) { benchmark(); } stopwatch.Stop(); double average = stopwatch.ElapsedMilliseconds/(double)runs; Log(String.Format("[{0}] Average of the {1} runs: {2:N2} ms", benchmarkName, runs, average)); wf.SetStatusLine((long)(average + 0.5)); }
public SheetTab(WorkbookForm gui, Sheet sheet) : base(sheet.Name) { this.gui = gui; this.sheet = sheet; this.Name = sheet.Name; this.dgv = new DataGridView(); dgv.ShowEditingIcon = false; dgv.Dock = DockStyle.Fill; Dock = DockStyle.Fill; // Display formula in the current cell and computed value in other cells dgv.CellFormatting += delegate(Object sender, DataGridViewCellFormattingEventArgs e) { int col = e.ColumnIndex, row = e.RowIndex; if (col == dgv.CurrentCellAddress.X && row == dgv.CurrentCellAddress.Y) { Object obj = sheet.Show(col, row); if (obj != null) { e.Value = obj; e.FormattingApplied = true; } } else { Object obj = sheet.ShowValue(col, row); if (obj != null) { e.Value = obj; e.FormattingApplied = true; } } }; // Show current cell's address, and show formula in formula box dgv.CellEnter += delegate(Object sender, DataGridViewCellEventArgs arg) { int row = arg.RowIndex, col = arg.ColumnIndex; dgv.TopLeftHeaderCell.Value = new CellAddr(col, row).ToString(); gui.formulaBox.Text = (String)dgv.CurrentCell.FormattedValue; }; // Check that cell's contents is well-formed after edit dgv.CellValidating += delegate(Object sender, DataGridViewCellValidatingEventArgs arg) { if (dgv.IsCurrentCellInEditMode) // Update only if cell was edited { int row = arg.RowIndex, col = arg.ColumnIndex; Object value = arg.FormattedValue; if (value != null) { SetCell(col, row, value.ToString(), arg); } } }; // Experiment with painting on the data grid view dgv.Paint += delegate(Object sender, PaintEventArgs arg) { base.OnPaint(arg); // Update column and row offset tables for drawing arrows between cells: int offset = dgv.RowHeadersWidth; for (int col = 0; col < sheet.Cols; col++) { colOffset[col] = offset; offset += dgv.Columns[col].Width; } colOffset[sheet.Cols] = offset; offset = dgv.ColumnHeadersHeight; for (int row = 0; row < sheet.Rows; row++) { rowOffset[row] = offset; offset += dgv.Rows[row].Height; } rowOffset[sheet.Rows] = offset; Pen pen = new Pen(Color.Blue, 1); pen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor; pen.StartCap = System.Drawing.Drawing2D.LineCap.RoundAnchor; if (dgv.SelectedCells.Count > 0) { DataGridViewCell dgvc = dgv.SelectedCells[0]; CellAddr ca = new CellAddr(dgvc.ColumnIndex, dgvc.RowIndex); Graphics g = arg.Graphics; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; int x = dgv.RowHeadersWidth, y = dgv.ColumnHeadersHeight, w = dgv.DisplayRectangle.Width - x, h = dgv.DisplayRectangle.Height - y; // Clip headers *before* the scroll translation/transform g.Clip = new Region(new Rectangle(x, y, w, h)); g.Transform = new System.Drawing.Drawing2D.Matrix(1, 0, 0, 1, -dgv.HorizontalScrollingOffset, -dgv.VerticalScrollingOffset); SupportArea.IdempotentForeach = false; // Draw all arrows into a cell DrawDependents(g, pen, gui.dependentsDepth, ca, new HashSet <CellAddr>()); DrawPrecedents(g, pen, gui.precedentsDepth, ca, new HashSet <CellAddr>()); } }; dgv.SelectionChanged += delegate(Object sender, EventArgs arg) { if (gui.dependentsDepth != 0 || gui.precedentsDepth != 0) { gui.dependentsDepth = gui.precedentsDepth = 0; Refresh(); } }; // Strange: to hold sheet, we need an extra row, but not an extra column? dgv.ColumnCount = sheet.Cols; dgv.RowCount = sheet.Rows + 1; // Allocate offset tables to assist drawing arrows between cells colOffset = new int[sheet.Cols + 1]; rowOffset = new int[sheet.Rows + 1]; dgv.AllowUserToAddRows = false; // Put labels on columns and rows, disable (meaningless) row sorting: for (int col = 0; col < dgv.ColumnCount; col++) { dgv.Columns[col].Name = CellAddr.ColumnName(col); dgv.Columns[col].SortMode = DataGridViewColumnSortMode.NotSortable; } for (int row = 0; row < dgv.RowCount; row++) { dgv.Rows[row].HeaderCell.Value = (row + 1).ToString(); } if (sheet.IsFunctionSheet) { DataGridViewCellStyle cellStyle = new DataGridViewCellStyle(); cellStyle.BackColor = Color.LightPink; dgv.ColumnHeadersDefaultCellStyle = dgv.RowHeadersDefaultCellStyle = cellStyle; } // Somewhat arbitrary extension of the width -- using // Graphics.MeasureString("0000", dgv.Font) would be better dgv.RowHeadersWidth += 20; Controls.Add(dgv); }
public void BenchmarkRecalculation(WorkbookForm wf, int runs) { BenchmarkWorkbook(wf, runs, "Workbook standard recalculation", wf.Workbook.Recalculate); }
public void BenchmarkRecalculationFullRebuild(WorkbookForm wf, int runs) { BenchmarkWorkbook(wf, runs, "Workbook full recalculation rebuild", wf.Workbook.RecalculateFullRebuild); }
public SdfForm(WorkbookForm gui, Workbook wb) { InitializeComponent(); this.gui = gui; PopulateFunctionListBox(false); }