设置环境:
我正在使用带有.NET framework 4的vb.net开发Excel 2010应用程序级外接程序。
我的目标:
表现是我的首要任务。我想通过利用.NET框架了解最快的方法。
在我的代码中使用ADO连接对象可以正常工作,但这个过程需要很长时间(5 - 8秒)。
这是我在名为井的表格中使用的SQL查询:
SELECT *
FROM wells
WHERE padgroup in
(SELECT padgroup
FROM wells
WHERE name LIKE 'TOMCHUCK 21-30'
OR name LIKE 'FEDERAL 41-25PH')
以下是表格的一部分:
我现在正在使用此代码创建一个ADO连接对象来检索我的结果:
'Create Recordset Object
rsCon = CreateObject("ADODB.Connection")
rsData = CreateObject("ADODB.Recordset")
rsCon.Open(szConnect)
rsData.Open(mySQLQueryToExecute, rsCon, 0, 1, 1)
'Check to make sure data is received, then copy the data
If Not rsData.EOF Then
TargetRange.Cells(1, 1).CopyFromRecordset(rsData)
Else
MsgBox("No records returned from : " & SourceFile, vbCritical)
End If
'Clean up the Recordset object
rsData.Close()
rsData = Nothing
rsCon.Close()
rsCon = Nothing
根据我所知,Excel电子表格以Open XML格式存储,.NET框架包含解析XML的本机支持。
经过研究,我发现了几个不同的选择:
有人可以提供一个指针,指出最好的方法吗?我真的很感激。
附加说明:
现在我只是将电子表格作为项目资源嵌入。
然后,在运行时我创建文件,运行查询,将结果存储在内存中,然后删除文件。
'Create temp file path in the commonapplicationdata folder
Dim excelsheetpath As StringBuilder
excelsheetpath = New StringBuilder(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData))
excelsheetpath.Append("\MasterList.xlsm")
'Save resources into temp location in HD
System.IO.File.WriteAllBytes(excelsheetpath.ToString, My.Resources.MasterList)
'Now call the function to use ADO to get records from the MasterList.xlsm file just created
GetData(excelsheetpath.ToString, "Sheet1", "A1:S40000", True, False)
'Store the results in-memory and display by adding to a datagridview control (in a custom task pane)
'Delete the spreadsheet
System.IO.File.Delete(excelsheetpath.ToString())
答案 0 :(得分:2)
您正在以错误的方式执行VSTO;)不要将SQL与Excel一起使用。如果您需要速度,请利用VSTO和本机Excel API。您可以跳过ADODB / OLEDB图层的开销,直接进入Excel对象模型,在Excel中使用超快速自动过滤器,SpecialCells
方法只将可见单元格放入多区域范围,{ {1}}将范围快速复制到数组的方法。
以下是VSTO 2010自定义工作簿示例,可快速搜索包含“aba”,“cat”或“zon”的a list of 58k words for words。
Value
答案 1 :(得分:0)
Excel 2010文件不完全是XML。获取XLSX(或XMSM)文件,并使用.zip扩展名重命名该文件。然后将其解压缩到一个新文件夹。子文件夹中的文件将是XML文件,是的,但实际的XLSX文件是一个zip文件,其中包含一组包含XML文件的文件夹。
我认为,最好的办法是使用ACE驱动程序(不再支持JET)并通过ODBC访问它。如果这还不够快,您可以在特定时间提取摘录并将其上传到可以运行查询的数据库;查询应该更快,但可能会过时。
答案 2 :(得分:0)
我的解决方案:
我尝试了三种不同的方法:
LINQ to XML提供了最佳性能。我将我的表转换为XML文件:
然后,在我的代码中,我使用StringReader引入 XMLwellData 文件(保存为项目资源)。
'welldoc will be the file to do queries on using LINQ to XML
Dim stream As System.IO.StringReader
stream = New StringReader(My.Resources.XMLwellData)
welldoc = XDocument.Load(stream)
'clean up stream now that it's no longer needed
stream.Close()
stream.Dispose()
'***** later in the code perform my query on XML file *********
Dim query = _
From well In welldoc.<wellList>.<well> _
Where well.<name>.Value Like "TOMCHUCK 21-30" _
Select well
For Each well in query
MessageBox.Show(well.<padgroup>.value)
Next
做我想做的事情非常简单,最重要的是它很快。
感谢您提供的所有帮助和建议。这对我来说很有意义。
使用Excel自动过滤器的替代方法
如果您尝试使用其他答案中建议的代码,则只会过滤两个值:
worksheet.Cells.AutoFilter(column, criteria, Excel.XlAutoFilterOperator.xlOr);
因此,对于filter with multiple criteria using Excel's Auotfilter,您必须将参数作为数组传递并过滤xlFilterValues。
Dim wrkbk As Excel.Workbook
Dim wrksht As Excel.Worksheet
Dim myRange As Excel.Range
Dim cell As Excel.Range
'You would add all of your wellnames to search to this List
Dim wellNames As New List(Of String)
wrksht = wrkbk.Sheets(1)
'In my excel file there is a Named Range which includes the all the information
myRange = wrksht.Range("WellLookUpTable")
'Notice, for `Criteria1:=` you MUST convert the List to an array
With wrksht.Range("WellLookUpTable")
.AutoFilter(Field:=2, Criteria1:=wellNames.ToArray, Operator:=Excel.XlAutoFilterOperator.xlFilterValues)
End With
myRange = wrksht.Range("A2", wrksht.Range("A2").End(Excel.XlDirection.xlDown)).Cells.SpecialCells(Excel.XlCellType.xlCellTypeVisible)
For Each cell In myRange
'column 11 is padgroup
MessageBox.Show(cell.Offset(0, 11).Value)
Next