2013-09-04 1 views
1

Как использовать вторую строку в Excel (xls & xlsx) в качестве заголовков столбцов при чтении ее через ADODB.Connection ???Excel ADO в ASP Classic - возвращает строку 2 как заголовок

  • в программе Excel от клиента
  • в программе Excel не может быть изменен до загружается на страницу ASP
  • Первая строка является TITLE отчета Excel (который я хочу, чтобы игнорировать)

Текущее решение (код находится в конце):

  1. Клиент загружает Excel
  2. Создать резервную копию как «оригинал»
  3. открыть и прочитать первые 2 строки Excel
  4. перезапись строка 1 со значениями из строки 2
  5. Первые 2 строки являются теперь идентичны
  6. Закрыть и повторное открытие Excel
  7. Выделить все, кроме значений, которые равны имени столбцов. -eg Выберите column1, column2, колонка3 ... от [Лист1 $], где UCase (column1) <> '' COLUMN1
  8. Чтение Excel и печать HTML

Возможные идеи, которые я не могу понять:

  • Назначение «именованного диапазона» на второй строке
  • Удалить первую строку (не выглядит возможным с помощью ADO и Excel)
  • Изменение заголовка Строка в строке 2 с HeaderRowRange.Address в VBA
  • Вместо того чтобы создавать копию в текущем решении, читать все из Ряда 2 и ниже, а затем сохранить в новый Excel

КОД ДЛЯ ТЕКУЩЕГО РЕШЕНИЕ:

' --------------------------------------------------------------------- 
' 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 
' -e.g. 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 
+0

Как о запуске 'SELECT COUNT (*)' из листа, чтобы определить количество строк, то 'выберите * ... где false', чтобы получить число столбцов. После этого вы можете определить диапазон, который вам нужно прочитать, и использовать это явно (например) 'select from [Sheet1 $ A2: E500]' –

+0

Поиск диапазона не является проблемой. В конечном счете, он может использовать Row 2 для заголовков столбцов, как и для Row 1. Предположим, что столбец 3 в строке 2 является «STATE», я хотел бы иметь возможность делать «select» из [Sheet1 $], где state = «Флорида» заказывает по штату, вместо того, чтобы делать «select» из [Sheet1 $], где F3 = «Флорида» по F3'. Поэтому, чтобы избежать необходимости записывать значения из строки 2 в строку 1. – SeaBass

ответ

1
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 
+0

Спасибо! Все еще нужны имена столбцов для некоторых сгенерированных SQL INSERTS перед печатью данных. Таким образом, строка 1 (скорее, A2) должна быть записана в массив или конкатенированную строку. Чтобы сначала получить строку 1, я бы изменил цикл FOR на 'For x = rsT.Fields.Count - 1 To x = 0'?Кроме того, если я пишу их в массив или конкатенированную строку, вы можете подумать о способе гарантировать, что порядок имен столбцов соответствует порядку данных? Наконец, существует ли существенная разница между вашей строкой подключения и моей? – SeaBass

+0

Имена полей не находятся ни в одной строке - они хранятся в коллекции полей Fields. Цикл My For - это цикл по столбцам, а не по строкам. –

+0

Правильно, по именам столбцов я понимаю, что это VALUE «Fields», а не «Имена полей». Я хотел спросить, можно ли сохранить VALUE для SQL INSERTS, но я думаю, что я понял, что часть ... внутри 'For Loop' продолжает добавлять имена с запятыми' sql_cols = sql_cols & "," & Field (#) .Value ' – SeaBass

Смежные вопросы