C# OleDb与Excel的连接;如何选择固定宽度、无限高度?
我正在使用OleDb从excel电子表格中选择数据。每个电子表格可以包含许多小表格,可能还包括标题和标签等家具。所以它可能看起来像这样,我们有两张桌子和一些标题 A B C D 1 . . . . 2 . . . . 3 Table1 . . . 4 Header1 HEADER2 . . 5 h huey . . 6 d dewey . . 7 l loius . . 8 s scrooge . . 9 . . . . 10 . . . . 11 . . . . 12 . . . . 13 . Table 2 . . 14 . HEADER1 HEADER2 HEADER3 15 . 1 foo x 16 . 2 bar y 17 . 3 baz z 18 . . . . 19 . . . . 选择表2中的数据,然后手动检查sentinel行,但这似乎不令人满意。Excel 2003只能读取65535行uint16,但Excel 2007可以读取更多uint32,因此我必须编写代码,根据文件扩展名.xls vs.xls?为Excel 2003和2007提供不同的查询 有人知道一种写查询的方法吗 '选择B14右下方的所有内容'? '选择B->D列中的所有内容' “选择B12:D*”其中*表示“您能做的一切”C# OleDb与Excel的连接;如何选择固定宽度、无限高度?,c#,excel,oledb,C#,Excel,Oledb,我正在使用OleDb从excel电子表格中选择数据。每个电子表格可以包含许多小表格,可能还包括标题和标签等家具。所以它可能看起来像这样,我们有两张桌子和一些标题 A B C D 1 . . . . 2 . . . . 3 Table1 . . .
两种可能的解决方案: 将表格放在单独的工作表上,然后简单地查询整个工作表。 在Excel 2007中为Excel中的每个表指定一个名称,选择该表,单击鼠标右键,然后选择“命名范围…”,然后在查询中使用此名称而不是Sheet1$B14:D65535。 希望有帮助 编辑 这里有第三个想法: 我不确定您使用什么来查询数据库,但如果您的查询引擎支持Sql Server之类的变量,例如,您可以存储 从服务器名称…表1中选择计数*$ …在一个名为@UsedRowCount的变量中,这将为您提供工作表中实际使用的行数。因此,@UsedRowCount=LastRowUsed-InitialBlankRows
然后,您可能可以使用字符串连接将65535替换为@UsedRowCount+@InitialBlankRows。在您的示例中,您必须将@InitialBlankRows设置为常量,它将是3,因为第一个表的标题行位于第4行。您说在上一步中,用户选择了标题。谁能说在当前感兴趣的区域下面没有几行空白,后面是另一个不相关的表格?我建议您让他们选择他们感兴趣的整个范围-这应该可以解决这两个问题。先决条件:您可以在代码中轻松确定最大行数 假设1每次选择都有很大的开销,所以一次选择一行很慢2选择64K或8M行,即使空白很慢。。。所以你想看看中间的某个地方是否更快。试试这个: 选择CHUNKSIZE,例如,如果不这样做,则在运行MAX_行时,每次减少100或1000行。为标记数据结束的空白行扫描每个块。 更新:实际回答明确的问题: 问:有人知道写一个查询的方法吗 Q1:‘选择B14右下方的所有内容’ A1:从[Sheet1$B12:]中选择*不起作用。您必须在Excel2003和Excel2007中执行…B12:IV。但是,您不需要它,因为您知道最右边的列是什么;见下文 Q2:“选择B->D列中的所有内容” A2:选择 *自[表1$B:D] Q3:“选择B12:D*”其中*表示“你能做的一切” A3:从[Sheet1$B12:D]中选择* 使用Python 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()
我会用约翰一次读1000行的解答 如果安装了Excel,还可以使用OLE自动化 我在Excel中记录了一个简单的宏,用于选择当前表中的最后一个单元格
Sub Macro2()
Range("B14").Select
Selection.End(xlDown).Select
//MsgBox ActiveCell.Address, vbOKOnly
End Sub
现在您只需将其翻译成C并读取活动单元格的地址。我们阅读了整个电子表格,即:从[Sheet1$]中选择*并处理应用程序代码中的所有其他内容。通过生成的OleDbDataReader很容易到达数据的起点并开始处理
这可能不是从Excel中提取数据的绝对最快的方法,但它是可靠的。谢谢,丹。不幸的是,我无法控制表单——它们是用户任意输入的,我只需要处理我得到的。明白了。我刚刚在我的答案中添加了第三个想法。删除额外的细节由应用程序处理;我从数据表中读取行,直到数据用完;我得到了一个完整的空白行。然后我自己终止阅读。不幸的是,我不能总是要求用户选择整个范围。在某些情况下,用户为电子表格选择一个标题,其中数据可以更改,但格式不能更改。例如,他们可能有固定标题的股票报价,包括公司、开盘价、收盘价、日期,但实际记录的数量会随着时间的推移而变化。如果他们选择50行,当行数>50时,导入将提供太少的数据。问题中需要的澄清请编辑:1选择一次,运行多个不选择,然后运行*多个。2当你说我从数据表中读取行直到数据用完时,有一个sentinel空白行标记数据的结尾3这是否意味着我从
从[Sheet1$B14:D65535]选择*直到的结果,还是说我选择一行直到?4在代码中确定最大行数是2^16还是2^20有多容易?Excel 2003工作表可以包含65536行,内部编号从0到65535,外部编号从1到65536。
Sub Macro2()
Range("B14").Select
Selection.End(xlDown).Select
//MsgBox ActiveCell.Address, vbOKOnly
End Sub