在现代企业中,数据的管理和交互是日常工作的重要组成部分。Excel作为一种广泛使用的电子表格软件,存储了大量的数据信息。然而,将这些数据发布到网络上,并允许用户与之交互,是一个挑战。本文将介绍一种方法,通过使用Excel作为数据源和引擎,来实现数据的导入和导出。
一家由不同产品研究员组成的公司,他们拥有关于不同产品(如DVD播放器、洗衣机等)的异构信息,这些信息存储在Excel文件中。有些Excel文件包含不同产品的比较表格,而另一些则包含基于产品信息的公式的电子表格。由于所有Excel文件在数据和结构上都完全不同,创建一个智能系统来将数据导入/导出到关系数据库将花费太多时间。因此,使用Excel作为数据源/引擎是解决这个问题的最佳方法。
组件必须能够根据输入数据检索结果数据(单元格范围)。组件必须使用Microsoft Office 10.0对象库。组件必须是可配置的,考虑以下方面:
组件的配置基于XML文件,具有以下模式:
<?xml version="1.0" encoding="utf-8"?>
<Configuration>
<TemporaryFolder>C:\Inetpub\wwwroot\ExcelParser\WindowsClient\Configuration</TemporaryFolder>
<ExcelFilePath>C:\Inetpub\wwwroot\ExcelParser\WindowsClient\ExcelSample\ExcelSample.xls</ExcelFilePath>
<Inputs>
<Input>
<Cell>A1</Cell>
<SheetIndex>1</SheetIndex>
<DataType>Values</DataType>
</Input>
</Inputs>
<Outputs>
<Output>
<DataType>Values</DataType>
<Start>A1</Start>
<End>C30</End>
<SheetIndex>2</SheetIndex>
<FullName>Test1</FullName>
</Output>
<Output>
<DataType>Chart</DataType>
<SheetIndex>2</SheetIndex>
<ChartIndex>1</ChartIndex>
<FullName>Chart</FullName>
</Output>
</Outputs>
</Configuration>
要向Excel传递值,组件会分析配置文件中声明的输入,获取指定工作表的实例,并将值设置到这些声明的输入单元格上。
foreach (Input input in this.Configuration.Inputs)
{
object value = inputs[i];
Input input = this.Configuration.Inputs[i];
Worksheet sheet = (Worksheet)book.Worksheets[input.SheetIndex];
Range range = sheet.get_Range(input.Cell, input.Cell);
range.set_Value(Missing.Value, value);
ReleaseComObject(range);
ReleaseComObject(sheet);
}
在配置中,应该有两种类型的数据需要从Excel文件中检索,值/范围或图表/图表。首先,组件获取指定的工作表并解析配置中声明的输出。获取的数据将被处理并添加到包含所有检索数据的哈希表中。
foreach (Output output in this.Configuration.Outputs)
{
Worksheet sheet = (Worksheet)book.Worksheets[output.SheetIndex];
if (output.DataType == OutputDataType.Values)
{
Range range = sheet.get_Range(output.Start, output.End);
this.Output.Add(output.FullName, range.Value2);
ReleaseComObject(range);
}
else if (output.DataType == OutputDataType.Chart)
{
ChartObjects chartobjects = (ChartObjects)sheet.ChartObjects(Missing.Value);
string tempFileName = GetFileName();
ChartObject chartobject = (ChartObject)chartobjects.Item(output.ChartIndex);
chartobject.Chart.Export(tempFileName, "GIF", false);
AddChart(output, tempFileName);
ReleaseComObject(chartobject);
ReleaseComObject(chartobjects);
}
ReleaseComObject(sheet);
}
必须调用ReleaseComObject来从内存中移除不会被.NET垃圾收集器考虑的COM对象实例。此方法用于明确控制从托管代码使用的COM对象的生命周期。否则,一些COM对象可能会保留在内存中。在这种情况下,EXCEL.exe进程在检索数据后不会被杀死。
原生地,当从Excel获取范围时,检索到的数据以二维数组的形式呈现。该组件将为配置中声明的每个范围创建一个datatable,并将其添加到输出哈希表中。
可以使用Parse方法的不同重载来实现这种通信:
Configuration config = Configuration.Read(this.textboxPath.Text);
Parser parser = new Parser();
parser.GetExcelOutputs(config, new object[] { this.textboxInput.Text });
或者,不指定输入值从Excel检索值:
Parser parser = new Parser();
parser.GetExcelOutputs(pathtoxmlconfiguration);
有两种方法可以显示哈希表中的数据:
以下是将datatable绑定到DataGridView,并将Chart图像放入PictureBox的一个示例:
this.dataGridView1.DataSource = parser.GetTable(0);
pictureBox1.Image = Image.FromStream(new MemoryStream(parser.GetChart(1)));
将找到Excel工作表、配置文件和组件在名为ExcelCommunicator的文件夹中的zip文件中,以及一个使用该组件和Excel文件的测试Windows应用程序。