Working in virtual mode (C# / netframework)
Note
This demo is available in your FlexCel installation at <FlexCel Install Folder>\samples\csharp\VS2022\netframework\10.API\22.Virtual Mode and also at https://github.com/tmssoftware/TMS-FlexCel.NET-demos/tree/master/csharp/VS2022/netframework/Modules/10.API/22.Virtual Mode
Overview
This example shows how to read or write Excel files without fully loading them in memory. See the FlexCel Performance Guide for more information in how Virtual Mode works.
Concepts
- How to read xls, xlsx or txt files without loading them into memory.
Files
AssemblyInfo.cs
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("(c) 2002 - 2024 TMS Software")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("7.21.0.0")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
CellReader.cs
using System;
using System.Collections.Generic;
using System.Text;
using FlexCel.Core;
using System.Drawing;
namespace VirtualMode
{
//A simple cell reader that will get the values from FlexCel and put them into a grid.
class CellReader
{
private bool Only50Rows;
private SparseCellArray CellData;
private bool FormatValues;
private int SheetToRead;
public DateTime StartSheetSelect;
public DateTime EndSheetSelect;
public CellReader(bool aOnly50Rows, SparseCellArray aCellData, bool aFormatValues)
{
Only50Rows = aOnly50Rows;
CellData = aCellData;
FormatValues = aFormatValues;
}
public void OnStartReading(object sender, VirtualCellStartReadingEventArgs e)
{
StartSheetSelect = DateTime.Now;
using (SheetSelectorForm SheetSelector = new SheetSelectorForm(e.SheetNames))
{
if (!SheetSelector.Execute())
{
EndSheetSelect = DateTime.Now;
e.NextSheet = null; //stop reading
return;
}
EndSheetSelect = DateTime.Now;
e.NextSheet = SheetSelector.SelectedSheet;
SheetToRead = SheetSelector.SelectedSheetIndex + 1;
}
}
public void OnCellRead(object sender, VirtualCellReadEventArgs e)
{
if (Only50Rows && e.Cell.Row > 50)
{
e.NextSheet = null; //Stop reading all sheets.
return;
}
if (e.Cell.Sheet != SheetToRead)
{
e.NextSheet = null; //Stop reading all sheets.
return;
}
if (FormatValues)
{
TUIColor Clr = Color.Empty;
CellData.AddValue(e.Cell.Row, e.Cell.Col,
TFlxNumberFormat.FormatValue(e.Cell.Value,
((ExcelFile)sender).GetFormat(e.Cell.XF).Format, ref Clr, ((ExcelFile)sender)));
}
else
{
CellData.AddValue(e.Cell.Row, e.Cell.Col, Convert.ToString(e.Cell.Value));
}
}
}
}
Form1.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using FlexCel.Core;
using FlexCel.XlsAdapter;
using System.Collections.Generic;
namespace VirtualMode
{
/// <summary>
/// A demo on how to read a file from FlexCel and display the results.
/// </summary>
public partial class mainForm: System.Windows.Forms.Form
{
SparseCellArray CellData; //we will store the data here. This is an example, in real world you would use "Virtual mode" to load the cells into your own structures.
public mainForm()
{
InitializeComponent();
ResizeToolbar(mainToolbar);
}
private void ResizeToolbar(ToolStrip toolbar)
{
using (Graphics gr = CreateGraphics())
{
double xFactor = gr.DpiX / 96.0;
double yFactor = gr.DpiY / 96.0;
toolbar.ImageScalingSize = new Size((int)(24 * xFactor), (int)(24 * yFactor));
toolbar.Width = 0; //force a recalc of the buttons.
}
}
private void btnExit_Click(object sender, System.EventArgs e)
{
Close();
}
private void btnInfo_Click(object sender, System.EventArgs e)
{
MessageBox.Show("This demo shows how to read the contents of an xls file without loading the file in memory.\n" +
"We will first load the sheet names in the file, then open just a single sheet, and read all or just the 50 first rows of it."
);
}
private void btnOpenFile_Click(object sender, System.EventArgs e)
{
if (openFileDialog1.ShowDialog() != DialogResult.OK) return;
ImportFile(openFileDialog1.FileName);
}
private void ImportFile(string FileName)
{
try
{
XlsFile xls = new XlsFile();
xls.VirtualMode = true; //Remember to turn virtual mode on, or the event won't be called.
//By default, FlexCel returns the formula text for the formulas, besides its calculated value.
//If you are not interested in formula texts, you can gain a little performance by ignoring it.
//This also works in non virtual mode.
xls.IgnoreFormulaText = cbIgnoreFormulaText.Checked;
CellData = new SparseCellArray();
//Attach the CellReader handler.
CellReader cr = new CellReader(cbFirst50Rows.Checked, CellData, cbFormatValues.Checked);
xls.VirtualCellStartReading += new VirtualCellStartReadingEventHandler(cr.OnStartReading);
xls.VirtualCellRead += new VirtualCellReadEventHandler(cr.OnCellRead);
DateTime StartOpen = DateTime.Now;
//Open the file. As we have a CellReader attached, the cells won't be loaded into memory, they will be passed to the CellReader
xls.Open(FileName);
DateTime StartSheetSelect = cr.StartSheetSelect;
DateTime EndSheetSelect = cr.EndSheetSelect;
DateTime EndOpen = DateTime.Now;
statusBar.Text = "Time to open file: " + (StartSheetSelect - StartOpen).ToString() + " Time to load file and fill grid: " + (EndOpen - EndSheetSelect).ToString();
//Set up grid.
GridCaption.Text = FileName;
if (CellData != null)
{
DisplayGrid.ColumnCount = CellData.ColCount;
DisplayGrid.RowCount = CellData.RowCount;
}
else
{
DisplayGrid.ColumnCount = 0;
DisplayGrid.RowCount = 0;
}
for (int i = 0; i < DisplayGrid.ColumnCount; i++)
{
DisplayGrid.Columns[i].Name = TCellAddress.EncodeColumn(i + 1);
}
}
catch
{
GridCaption.Text = "Error Loading File";
CellData = null;
throw;
}
}
private void DisplayGrid_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
//Show the row number in the grid at the left
string r = (e.RowIndex + 1).ToString();
SizeF textSize = e.Graphics.MeasureString(r, DisplayGrid.Font);
if (DisplayGrid.RowHeadersWidth < (int)(textSize.Width + 20)) DisplayGrid.RowHeadersWidth = (int)(textSize.Width + 20);
e.Graphics.DrawString(r, DisplayGrid.Font, SystemBrushes.ControlText, e.RowBounds.Left + DisplayGrid.RowHeadersWidth - textSize.Width - 5, e.RowBounds.Location.Y + ((e.RowBounds.Height - textSize.Height) / 2f));
}
private void DisplayGrid_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
if (CellData == null)
{
e.Value = null;
return;
}
if (e.RowIndex >= CellData.RowCount)
{
e.Value = null;
return;
}
e.Value = CellData.GetValue(e.RowIndex + 1, e.ColumnIndex + 1);
}
}
}
Form1.Designer.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using FlexCel.Core;
using FlexCel.XlsAdapter;
namespace VirtualMode
{
public partial class mainForm: System.Windows.Forms.Form
{
private System.Windows.Forms.OpenFileDialog openFileDialog1;
private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.StatusBar statusBar;
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(mainForm));
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.panel2 = new System.Windows.Forms.Panel();
this.cbFormatValues = new System.Windows.Forms.CheckBox();
this.cbIgnoreFormulaText = new System.Windows.Forms.CheckBox();
this.cbFirst50Rows = new System.Windows.Forms.CheckBox();
this.statusBar = new System.Windows.Forms.StatusBar();
this.DisplayGrid = new System.Windows.Forms.DataGridView();
this.GridCaptionPanel = new System.Windows.Forms.Panel();
this.GridCaption = new System.Windows.Forms.Label();
this.mainToolbar = new System.Windows.Forms.ToolStrip();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.btnOpenFile = new System.Windows.Forms.ToolStripButton();
this.btnExit = new System.Windows.Forms.ToolStripButton();
this.btnInfo = new System.Windows.Forms.ToolStripButton();
this.panel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.DisplayGrid)).BeginInit();
this.GridCaptionPanel.SuspendLayout();
this.mainToolbar.SuspendLayout();
this.SuspendLayout();
//
// openFileDialog1
//
this.openFileDialog1.DefaultExt = "xls";
this.openFileDialog1.Filter = "Excel Files|*.xls;*.xlsx;*.xlsm|Excel 97/2003|*.xls|Excel 2007|*.xlsx;*.xlsm|All " +
"files|*.*";
this.openFileDialog1.Title = "Open an Excel File";
//
// panel2
//
this.panel2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panel2.Controls.Add(this.cbFormatValues);
this.panel2.Controls.Add(this.cbIgnoreFormulaText);
this.panel2.Controls.Add(this.cbFirst50Rows);
this.panel2.Dock = System.Windows.Forms.DockStyle.Top;
this.panel2.Location = new System.Drawing.Point(0, 38);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(880, 25);
this.panel2.TabIndex = 4;
//
// cbFormatValues
//
this.cbFormatValues.AutoSize = true;
this.cbFormatValues.Location = new System.Drawing.Point(269, 5);
this.cbFormatValues.Name = "cbFormatValues";
this.cbFormatValues.Size = new System.Drawing.Size(131, 17);
this.cbFormatValues.TabIndex = 2;
this.cbFormatValues.Text = "Format values (slower)";
this.cbFormatValues.UseVisualStyleBackColor = true;
//
// cbIgnoreFormulaText
//
this.cbIgnoreFormulaText.AutoSize = true;
this.cbIgnoreFormulaText.Checked = true;
this.cbIgnoreFormulaText.CheckState = System.Windows.Forms.CheckState.Checked;
this.cbIgnoreFormulaText.Location = new System.Drawing.Point(150, 5);
this.cbIgnoreFormulaText.Name = "cbIgnoreFormulaText";
this.cbIgnoreFormulaText.Size = new System.Drawing.Size(113, 17);
this.cbIgnoreFormulaText.TabIndex = 1;
this.cbIgnoreFormulaText.Text = "Ignore formula text";
this.cbIgnoreFormulaText.UseVisualStyleBackColor = true;
//
// cbFirst50Rows
//
this.cbFirst50Rows.AutoSize = true;
this.cbFirst50Rows.Checked = true;
this.cbFirst50Rows.CheckState = System.Windows.Forms.CheckState.Checked;
this.cbFirst50Rows.Location = new System.Drawing.Point(11, 5);
this.cbFirst50Rows.Name = "cbFirst50Rows";
this.cbFirst50Rows.Size = new System.Drawing.Size(133, 17);
this.cbFirst50Rows.TabIndex = 0;
this.cbFirst50Rows.Text = "Read only first 50 rows";
this.cbFirst50Rows.UseVisualStyleBackColor = true;
//
// statusBar
//
this.statusBar.Location = new System.Drawing.Point(0, 439);
this.statusBar.Name = "statusBar";
this.statusBar.Size = new System.Drawing.Size(880, 22);
this.statusBar.TabIndex = 7;
//
// DisplayGrid
//
this.DisplayGrid.AllowUserToAddRows = false;
this.DisplayGrid.AllowUserToDeleteRows = false;
dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.DisplayGrid.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
this.DisplayGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.DisplayGrid.Dock = System.Windows.Forms.DockStyle.Fill;
this.DisplayGrid.Location = new System.Drawing.Point(0, 86);
this.DisplayGrid.Name = "DisplayGrid";
this.DisplayGrid.ReadOnly = true;
this.DisplayGrid.Size = new System.Drawing.Size(880, 353);
this.DisplayGrid.TabIndex = 8;
this.DisplayGrid.VirtualMode = true;
this.DisplayGrid.CellValueNeeded += new System.Windows.Forms.DataGridViewCellValueEventHandler(this.DisplayGrid_CellValueNeeded);
this.DisplayGrid.RowPostPaint += new System.Windows.Forms.DataGridViewRowPostPaintEventHandler(this.DisplayGrid_RowPostPaint);
//
// GridCaptionPanel
//
this.GridCaptionPanel.BackColor = System.Drawing.SystemColors.ActiveCaption;
this.GridCaptionPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.GridCaptionPanel.Controls.Add(this.GridCaption);
this.GridCaptionPanel.Dock = System.Windows.Forms.DockStyle.Top;
this.GridCaptionPanel.ForeColor = System.Drawing.SystemColors.ActiveCaptionText;
this.GridCaptionPanel.Location = new System.Drawing.Point(0, 63);
this.GridCaptionPanel.Name = "GridCaptionPanel";
this.GridCaptionPanel.Size = new System.Drawing.Size(880, 23);
this.GridCaptionPanel.TabIndex = 9;
//
// GridCaption
//
this.GridCaption.AutoSize = true;
this.GridCaption.Location = new System.Drawing.Point(13, 6);
this.GridCaption.Name = "GridCaption";
this.GridCaption.Size = new System.Drawing.Size(0, 13);
this.GridCaption.TabIndex = 0;
//
// mainToolbar
//
this.mainToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.btnOpenFile,
this.toolStripSeparator1,
this.btnExit,
this.btnInfo});
this.mainToolbar.Location = new System.Drawing.Point(0, 0);
this.mainToolbar.Name = "mainToolbar";
this.mainToolbar.Size = new System.Drawing.Size(880, 38);
this.mainToolbar.TabIndex = 10;
this.mainToolbar.Text = "toolStrip1";
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(6, 38);
//
// btnOpenFile
//
this.btnOpenFile.Image = ((System.Drawing.Image)(resources.GetObject("btnOpenFile.Image")));
this.btnOpenFile.ImageTransparentColor = System.Drawing.Color.Magenta;
this.btnOpenFile.Name = "btnOpenFile";
this.btnOpenFile.Size = new System.Drawing.Size(59, 35);
this.btnOpenFile.Text = "Open file";
this.btnOpenFile.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
this.btnOpenFile.Click += new System.EventHandler(this.btnOpenFile_Click);
//
// btnExit
//
this.btnExit.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.btnExit.Image = ((System.Drawing.Image)(resources.GetObject("btnExit.Image")));
this.btnExit.ImageTransparentColor = System.Drawing.Color.Magenta;
this.btnExit.Name = "btnExit";
this.btnExit.Size = new System.Drawing.Size(59, 35);
this.btnExit.Text = " E&xit ";
this.btnExit.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
this.btnExit.Click += new System.EventHandler(this.btnExit_Click);
//
// btnInfo
//
this.btnInfo.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.btnInfo.Image = ((System.Drawing.Image)(resources.GetObject("btnInfo.Image")));
this.btnInfo.ImageTransparentColor = System.Drawing.Color.Magenta;
this.btnInfo.Name = "btnInfo";
this.btnInfo.Size = new System.Drawing.Size(74, 35);
this.btnInfo.Text = "Information";
this.btnInfo.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
this.btnInfo.Click += new System.EventHandler(this.btnInfo_Click);
//
// mainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(880, 461);
this.Controls.Add(this.DisplayGrid);
this.Controls.Add(this.GridCaptionPanel);
this.Controls.Add(this.panel2);
this.Controls.Add(this.statusBar);
this.Controls.Add(this.mainToolbar);
this.Name = "mainForm";
this.Text = "Virtual Mode Example - Cells are not stored in memory";
this.panel2.ResumeLayout(false);
this.panel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.DisplayGrid)).EndInit();
this.GridCaptionPanel.ResumeLayout(false);
this.GridCaptionPanel.PerformLayout();
this.mainToolbar.ResumeLayout(false);
this.mainToolbar.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private DataGridView DisplayGrid;
private Panel GridCaptionPanel;
private Label GridCaption;
private ToolStrip mainToolbar;
private ToolStripButton btnOpenFile;
private ToolStripSeparator toolStripSeparator1;
private ToolStripButton btnInfo;
private ToolStripButton btnExit;
private CheckBox cbFirst50Rows;
private CheckBox cbIgnoreFormulaText;
private CheckBox cbFormatValues;
}
}
Program.cs
using System;
using System.Windows.Forms;
namespace VirtualMode
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new mainForm());
}
}
}
SheetSelectorForm.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace VirtualMode
{
public partial class SheetSelectorForm: Form
{
public SheetSelectorForm()
{
InitializeComponent();
}
public SheetSelectorForm(string[] SheetNames)
: this()
{
foreach (string s in SheetNames)
{
SheetList.Items.Add(s);
}
SheetList.SelectedIndex = 0;
}
internal bool Execute()
{
return ShowDialog() == DialogResult.OK;
}
public string SelectedSheet
{
get
{
return Convert.ToString(SheetList.SelectedItem);
}
}
public int SelectedSheetIndex
{
get
{
return SheetList.SelectedIndex;
}
}
private void SheetList_DoubleClick(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
}
}
}
SheetSelectorForm.Designer.cs
namespace VirtualMode
{
partial class SheetSelectorForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.btnOk = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.SheetList = new System.Windows.Forms.ListBox();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.Controls.Add(this.btnCancel);
this.panel1.Controls.Add(this.btnOk);
this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom;
this.panel1.Location = new System.Drawing.Point(0, 217);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(284, 45);
this.panel1.TabIndex = 0;
//
// btnOk
//
this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnOk.Location = new System.Drawing.Point(116, 10);
this.btnOk.Name = "btnOk";
this.btnOk.Size = new System.Drawing.Size(75, 23);
this.btnOk.TabIndex = 0;
this.btnOk.Text = "Ok";
this.btnOk.UseVisualStyleBackColor = true;
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(197, 10);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 1;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
//
// SheetList
//
this.SheetList.Dock = System.Windows.Forms.DockStyle.Fill;
this.SheetList.FormattingEnabled = true;
this.SheetList.Location = new System.Drawing.Point(0, 0);
this.SheetList.Name = "SheetList";
this.SheetList.Size = new System.Drawing.Size(284, 217);
this.SheetList.TabIndex = 1;
this.SheetList.DoubleClick += new System.EventHandler(this.SheetList_DoubleClick);
//
// SheetSelectorForm
//
this.AcceptButton = this.btnOk;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.SheetList);
this.Controls.Add(this.panel1);
this.Name = "SheetSelectorForm";
this.Text = "Select sheet to load...";
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Button btnOk;
private System.Windows.Forms.ListBox SheetList;
}
}
SparseCellArray.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace VirtualMode
{
/// <summary>
/// This is a simple class that holds cell values. Items are supposed to
/// be entered in sorted order, and it isn't really production-ready, just
/// to be used in a demo.
/// </summary>
class SparseCellArray
{
List<SparseRow> Data;
int FColCount;
public SparseCellArray()
{
FColCount = 0;
}
public void AddValue(int Row, int Col, string Value)
{
if (Col > FColCount) FColCount = Col;
if (Data == null) Data = new List<SparseRow>();
SparseRow SpRow = new SparseRow(Row);
int Idx = Data.BinarySearch(SpRow);
if (Idx < 0)
{
SpRow.CreateData();
Data.Insert(~Idx, SpRow);
}
else SpRow = Data[Idx];
SparseCell SpCell = new SparseCell(Col, Value);
Idx = SpRow.Data.BinarySearch(SpCell);
if (Idx < 0)
{
SpRow.Data.Insert(~Idx, SpCell);
}
else
{
SpRow.Data[Idx] = SpCell;
}
}
public string GetValue(int Row, int Col)
{
if (Data == null) return null;
SparseRow SpRow = new SparseRow(Row);
int Idx = Data.BinarySearch(SpRow);
if (Idx < 0) return null;
SpRow = Data[Idx];
SparseCell SpCell = new SparseCell(Col, null);
Idx = SpRow.Data.BinarySearch(SpCell);
if (Idx < 0) return null;
return SpRow.Data[Idx].Value;
}
public int ColCount { get { return FColCount; } }
public int RowCount
{
get
{
if (Data == null || Data.Count == 0) return 0;
return Data[Data.Count - 1].Row;
}
}
}
struct SparseRow: IComparable<SparseRow>
{
public int Row;
public List<SparseCell> Data;
public SparseRow(int aRow)
{
Row = aRow;
Data = null;
}
public void CreateData()
{
Data = new List<SparseCell>();
}
#region IComparable<SparseRow> Members
public int CompareTo(SparseRow other)
{
return Row.CompareTo(other.Row);
}
#endregion
}
class SparseCell: IComparable<SparseCell>
{
public int Col;
public string Value;
public SparseCell(int aCol, string aValue)
{
Col = aCol;
Value = aValue;
}
#region IComparable<SparseCell> Members
public int CompareTo(SparseCell other)
{
return Col.CompareTo(other.Col);
}
#endregion
}
}