OleDb连接到Excel; 我如何select固定宽度,无限高度?
我使用OleDb从Excel电子表格中select数据。 每个电子表格可以包含许多小表,并可能包含标题和标签之类的家具。 所以它可能看起来像这样,我们有两张桌子和一些标题;
A B C D 1。 。 。 。 2。 。 。 。 3表1。 。 。 4 Header1 HEADER2。 。 5 h huey。 。 6 d杜威。 。 7 l loius。 。 8 s sc。。 。 9。 。 。 。 10。 。 。 。 11。 。 。 。 12。 。 。 。 13。 表2 。 14。 HEADER1 HEADER2 HEADER3 15。 1 foo x 16。 2巴y 17。 3 baz z 18。 。 。 。 19。 。 。 。
在之前的步骤中,用户已经select了他们感兴趣的表格的标题; 在这种情况下,看表2他们将select范围B14:D14
。
这些设置被保存,然后我需要查询该表。 随着电子表格数据的更新,可能会一遍又一遍地发生; 任何时候都可以添加更多的行,但是标题总是固定的。 有一个标记(空白行)标记数据的结束
要select表中的数据,我正在写这样的查询;
SELECT * FROM [Sheet1$B14:D65535]
select表2中的数据,然后手动检查哨兵行,但这似乎并不令人满意。 Excel 2003只能读取65,535行(uint16),但是Excel 2007可以读取更多(uint32),因此我必须编写代码,以便根据文件的扩展名(.xls和.xls)为Excel 2003和2007提供不同的查询。 XLS?)。
有谁知道一种方式来写一个查询说:
- “select所有的东西,B14的权利?
- 'select列B-> D'
- 'select B12:D *'其中*表示“所有你可以做的”
先决条件:您可以在代码中轻松确定最大行数是多less。
假设(1)每个SELECT有很大的开销,所以一次select一行很慢(2)select64K或8M行(即使是空白)很慢…所以你想看看在中间的某个地方是否可以更快。 尝试这个:
一次selectCHUNKSIZE(例如100或1000)行(更less的情况下,否则会超出MAX_ROWS)。 扫描每个块的空白行标记数据结束。
更新:其实回答明确的问题:
问:有没有人知道写一个查询的方法,
Q1:“selectB14的所有东西”?
A1: select * from [Sheet1$B12:]
不起作用。 你将不得不做...B12:IV
在Excel 2003中,而不pipe它在Excel 2007中。但是,你不需要这样做,因为你知道你最右边的列是什么; 见下文。
Q2:select列B-> D中的所有内容
A2: select * from [Sheet1$B:D]
问题3:'selectB12:D *
'其中*
表示“所有你可以做的”
A3:select * from [Sheet1 $ B12:D]
使用以下代码testingPython 2.5:
import win32com.client import sys filename, sheetname, range = sys.argv[1:4] DSN= """ PROVIDER=Microsoft.Jet.OLEDB.4.0; DATA SOURCE=%s; Extended Properties='Excel 8.0;READONLY=true;IMEX=1'; """ % filename conn = win32com.client.Dispatch("ADODB.Connection") conn.Open(DSN) rs = win32com.client.Dispatch("ADODB.Recordset") sql = ( "SELECT * FROM [Excel 8.0;HDR=NO;IMEX=1;Database=%s;].[%s$%s]" % (filename, sheetname, range) ) rs.Open(sql, conn) nrows = 0 while not rs.EOF: nrows += 1 nf = rs.Fields.Count values = [rs.Fields.Item(i).Value for i in xrange(nf)] print nrows, values if not any(value is not None for value in values): print "sentinel found" break rs.MoveNext() rs.Close() conn.Close()
情侣可能的解决
- 把你的表放在单独的工作表上,然后简单地查询整个工作表。
- 为Excel中的每个表提供一个名称(在Excel 2007中,select该表,右键单击并select“命名范围…”),然后在查询中使用该名称而不是“Sheet1 $ B14:D65535”。
希望有所帮助。
编辑
这是第三个想法:
我不知道你用什么来查询你的数据库,但如果你的查询引擎支持variables(如Sql Server,例如),你可以存储的结果…
SELECT COUNT(*)FROM NameOfServer … Sheet1 $
…在一个名为@UsedRowCount的variables中,它会给你在工作表中实际使用的行数。 所以,@UsedRowCount = LastRowUsed – InitialBlankRows。
然后,您可以使用string连接来将“65535”replace为@UsedRowCount + @InitialBlankRows。 你将不得不将@InitialBlankRows设置为一个常量(在你的例子中,这将是3,因为第一个表的标题行位于第4行)。
你说在上一步中,用户已经select了标题。 谁会说在目前的利益地区之下,有不less的空白的行跟着另一个不相关的表呢? 我build议你让他们select他们感兴趣的整个范围 – 这应该解决这两个问题。
我会用John的解决scheme(一次读1000行)。
如果你安装了Excel,你也可以使用OLE自动化。
我已经logging了一个简单的macros,在Excel中select当前表中的最后一个单元格。
Sub Macro2() Range("B14").Select Selection.End(xlDown).Select //MsgBox ActiveCell.Address, vbOKOnly End Sub
Sub Macro2() Range("B14").Select Selection.End(xlDown).Select //MsgBox ActiveCell.Address, vbOKOnly End Sub
现在,您只需要在C#中将其翻译并读取活动单元格的地址即可。
我们阅读整个电子表格(即:SELECT * FROM [Sheet1 $]),并处理我们应用程序代码中的所有其他内容。 通过OleDbDataReader进行竞争以获取数据的起始点并开始处理非常简单。
它可能不是从Excel中吸取数据的绝对最快的方法,但它是可靠的。
- OleDbDataAdapter.Fill(DataTable)不能处理大的xls文件大小
- 从Excel中读取NUnittesting数据 – 如何访问testing数据?
- 通过.NET源代码中的公式将数据导入到Excel电子表格中的适当技术是什么?
- Excel数据提取 – 发布列数据types
- 如何使用C#和EPPlus为工作簿设置Excel Color Theme
- 从C#到VBA转换(是的,一种愚蠢的)
- 如何解决无法投射“System.Data.DataView”types的对象来键入“System.Data.DataTable”错误
- 将页脚添加到Excel表集合
- 如何在C#中使用NPOI Excel添加单元格注释?