ASP经典中的Excel ADO – 将第2行作为标题返回

在通过ADODB.Connection读取时,如何将Excel(xls&xlsx)中的第二行用作列标题?

  • Excel来自客户端
  • 在上传到ASP页面之前,Excel不能被修改
  • 第一行是Excel报告的标题(我想忽略)

目前的解决scheme(代码在最后):

  1. 客户端上传Excel
  2. 创build备份副本为“原始”
  3. 打开并读取前两行的Excel
  4. 用行2中的值覆盖第1行
  5. 前两行现在是相同的
  6. closures并重新打开Excel
  7. select除了与列名称名相等的值以外的所有内容-eg从[Sheet1 $]中selectcolumn1,column2,column3 …,其中ucase(column1)<>'COLUMN1'
  8. 阅读Excel和打印HTML

可能的想法,我不明白:

  • 为第二行分配一个“命名范围”
  • 删除第一行(用ADO和Excel不可能)
  • 使用VBA中的HeaderRowRange.Address将标题行更改为第2行
  • 不要在当前的解决scheme中创build副本,请阅读第2行及以下的所有内容,然后保存到新的Excel中

当前解决scheme的代码:

' --------------------------------------------------------------------- ' 1. Client uploads Excel ' --------------------------------------------------------------------- xlsfolder = "D:\website\excels\" filename = request("filename_from_asp_upload_form") xlsfile = xlsfolder & filename ' --------------------------------------------------------------------- ' 2. Create backup copy as "original" ' --------------------------------------------------------------------- dim fscopy set fscopy=Server.CreateObject("Scripting.FileSystemObject") exceltypelower = fscopy.GetExtensionName(xlsfile) replace_text = "_BACKUP." & exceltypelower xlsfile_copy = replace(xlsfile, ("." & exceltypelower), replace_text) fscopy.CopyFile xlsfile,xlsfile_copy set fscopy=nothing ' --------------------------------------------------------------------- ' EXTRA STEP - SELECT EXCEL DRIVER ' --------------------------------------------------------------------- if exceltype = "XLS" then exceldriver = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & xlsfile & ";Extended Properties=""Excel 8.0;""" elseif exceltype = "XLSX" then exceldriver = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & xlsfile & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""" exceldriver2 = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & xlsfile & ";Extended Properties=""Excel 8.0;HDR=No;""" '*** Second driver allows first row to be read as data and not header allowing Excel cells to be overwritten else '**** default to 97-2003 format. ELSE just in case exceldriver = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & xlsfile & ";Extended Properties=""Excel 8.0;""" end if ' --------------------------------------------------------------------- ' 3. Open and Read first 2 rows of Excel ' 4. Overwrite row 1 with values from row 2 ' --------------------------------------------------------------------- ' NOTE: There is another step at UPLOAD that the user flags what kind of Excel Report it is. ' Since there are just a few now, I have the skip_title variable hard-coded ' IF SKIP_TITLE = "Y"... that means the column headers are on row 2 ' IF SKIP_TITLE = "N"... that means the column headers are on row 1 and this is unnecessary ' --------------------------------------------------------------------- if skip_title = "Y" then excel_query2 = "Select * from [Sheet1$] " Const adOpenStatic = 3 Const adLockOptimistic = 3 Const adUseClient = 3 Set objConn = CreateObject("ADODB.Connection") Set objRecordset = CreateObject("ADODB.Recordset") objConn.Open (exceldriver2) objRecordset.CursorLocation = adUseClient objRecordset.Open excel_query2 , objConn, adOpenStatic, adLockOptimistic counter = 1 headcount = 0 colcount = objRecordSet.Fields.Count ' How many columns there are to traverse p = objRecordSet.GetRows(colcount,0) ' Write excel_query2 results for number of columns above objRecordSet.MoveFirst do until objRecordSet.EOF or counter = 0 for each x in objRecordSet.Fields objRecordSet.Fields(headcount).Value = p(headcount, 1) 'overwrite row 1 with row 2 headcount = headcount + 1 next counter = counter - 1 objRecordSet.MoveNext loop objRecordSet.Update objRecordset.Close objConn.Close end if ' --------------------------------------------------------------------- ' 5. The first 2 rows are now identical ' 6. Close and Re-Open Excel ' --------------------------------------------------------------------- set objConnection = Server.CreateObject("ADODB.Connection") objConnection.Open (exceldriver) ' --------------------------------------------------------------------- ' 7. Select everything except values that equal name of column names ' -eg Select column1, column2, column3... from [Sheet1$] where ucase(column1) <> 'COLUMN1' ' --------------------------------------------------------------------- excel_query = "Select column1, column2, column3... from [Sheet1$] where ucase(column1) <> 'COLUMN1' " 'example set objRS = objConnection.execute(excel_query) ' --------------------------------------------------------------------- ' 8. Read Excel and Print HTML ' --------------------------------------------------------------------- response.write "<table><thead><tr>" for each x in objRS.Fields response.write("<th>" & ucase(x.name) & "</th>") next response.write "</tr></thead>" response.write "<tbody>" do until objRS.EOF response.write "<tr>" for each fld in objRS.Fields response.write "<td>" & fld.value & "</td>" next response.write "</tr>" objRS.MoveNext loop objRS.close objConnection.Close response.write "</tbody></table>" ' --------------------------------------------------------------------- ' Le Fin or Da End 

 Sub Test22() Dim cn As New ADODB.Connection Dim rsT As New ADODB.Recordset Dim numCols As Long, numRows As Long, x As Long With cn .Provider = "Microsoft.Jet.OLEDB.4.0" .ConnectionString = "Data Source=" & ThisWorkbook.Path & _ "\ADOXSource.xls;Extended Properties=Excel 8.0;" .CursorLocation = adUseClient .Open End With 'read the whole sheet rsT.Open "select * from [Sheet1$]", cn rsT.MoveLast 'get # of rows/cols numCols = rsT.Fields.Count numRows = rsT.RecordCount rsT.Close 'get data from specific range rsT.Open "select * from [Sheet1$A2:" & Chr(64 + numCols) & (numRows - 1) & "]", cn 'I'm testing this in excel... For x = 0 To rsT.Fields.Count - 1 Sheet1.Range("a1").Offset(0, x).Value = rsT.Fields(x).Name Next x Sheet1.Range("a2").CopyFromRecordset rsT End Sub