Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB6 > Использование файлов, найденных FileSearch'ем.


Автор: Йекс 17.11.2006, 11:59
Господа, подскажите ламеру. Суть проблемы:
Я при помощи FileSearh нахожу необходиме мне файлы типа xls. в папке "Книги".  Далее из каждого это файла необходимо взять данные с ячйки А1 и занести в ту таблицу, с которой запускается макрос (в ячейки а1, а2, а3 и тп по порядку) . Как это сотворить?

Set fs = Application.FileSearch
With fs
    .LookIn = "E:\Книги"
    .Filename = "*.xls"
    If .Execute > 0 Then
          For i = 1 To .FoundFiles.Count
              Range("a" & i) = ?????????????????    
          Next  i
     End If
End With

Или как эти найденные адреса можно использовать в формулах?

Автор: Naghual 17.11.2006, 12:19
Необходимо в цикле открытькаждый из файлов и получить данные из открытой книги.

Автор: Йекс 25.11.2006, 15:08
Цитата

Необходимо в цикле открытькаждый из файлов и получить данные из открытой книги. 

Да так у меня и было. Только это не очень удобно, так как файлов много и весь этот процесс занимает слишком много времени.  Как это сделать, не открывая файлы?

Автор: mihanik 26.11.2006, 10:44
Цитата(Йекс @  25.11.2006,  15:08 Найти цитируемый пост)
Как это сделать, не открывая файлы? 


Как ты себе это представляешь? smile 

По аналогии.
Ты хочешь узнать, что написано на первой странице книги, не открывая эту самую книгу...
Такое возможно? smile  smile   smile 

Автор: Йекс 26.11.2006, 17:30
Цитата

Как ты себе это представляешь?

Ну примерно если я в какой-либо ячейке напишу формулу типа "='E:\[Книга3.xls]Лист1'!$C$4", то в данной ячейке будут данные из книги3 из ячейки С4. То есть не открывая книгу3 я забил из неё данные в текущую книгу.

Автор: Naghual 26.11.2006, 23:01
smile 

Все бы хорошо, только то КАК ты себе это представляеш, работает совсем НЕ ТАК.
Нужный файл открывается в любом случае. Просто это делает сам Эксель прозрачно для пользователя.

Автор: Йекс 27.11.2006, 16:10
Цитата

Все бы хорошо, только то КАК ты себе это представляеш, работает совсем НЕ ТАК.
Нужный файл открывается в любом случае. Просто это делает сам Эксель прозрачно для пользователя.

Вполне может быть. Тогда возникает вопрос, как сделать так, чтобы Эксель открывал файлы "прозрачно" для меня, а не просто Workbooks.Open.

Автор: Naghual 27.11.2006, 16:19
Workbooks.Open - это и есть прозрачно для Пользователя.
Не прозрачно это только для программиста.

Автор: Aloha 28.11.2006, 01:13
Йекс

Я опробовал два варианта и сравнил их быстродействие. Вот что получилось (тестировал на специально созданных для этой цели 1000 Excel файлов, ячейка A1 которых содержит имя файла):

1 вариант
Этот вариант уже озвучен: Workbooks.Open ... Close.
Код
Sub s_Test_1()
  Dim v_FSO As Object
  Dim v_Wb As Workbook
  Dim v_Folder As String
  Dim n As Integer

  v_Folder = "E:\Книги\"
  Set v_FSO = CreateObject("Scripting.FileSystemObject")
  Application.ScreenUpdating = False
  For Each x In v_FSO.GetFolder(v_Folder).Files
    If v_FSO.GetExtensionName(x) = "xls" Then
      Set v_Wb = Workbooks.Open(v_Folder & x.Name)
      n = n + 1
      ThisWorkbook.Sheets(1).Cells(n, 1) = v_Wb.Sheets(1).Range("A1")
      v_Wb.Close
    End If
  Next
  Application.ScreenUpdating = True
  Set v_FSO = Nothing
End Sub

Примечание:
  • Здесь для отбора файлов использован объект FileSystemObject (а не FileSearch)
  • Данные заносятся в первый стобец листа (а не в строку), т.к. обрабатывается 1000 файлов (>256)
2 вариант

Здесь для доступа к данным используется ADO
Код
Sub s_Test_2()
  Dim v_FSO As Object
  Dim v_Cnn As Object
  Dim v_Rst As Object
  Dim v_Wb As Workbook
  Dim v_Folder As String
  Dim v_SQL As String
  Dim n As Integer

  v_Folder = "E:\Книги\"
  Set v_FSO = CreateObject("Scripting.FileSystemObject")
  Application.ScreenUpdating = False
  For Each x In v_FSO.GetFolder(v_Folder).Files
    If v_FSO.GetExtensionName(x) = "xls" Then
      Set v_Cnn = CreateObject("ADODB.Connection")
      With v_Cnn
        .Provider = "Microsoft.Jet.OLEDB.4.0"
        .ConnectionString = "Data Source=" & v_Folder & x.Name & ";" & _
                            "Extended Properties=""Excel 8.0; HDR=No;"""
        .Open
      End With
      Set v_Rst = CreateObject("ADODB.Recordset")
      v_SQL = "SELECT * FROM [Лист1$A1:A1]"
      v_Rst.Open v_SQL, v_Cnn
      n = n + 1
      ThisWorkbook.Sheets(1).Cells(n, 1).CopyFromRecordset v_Rst
    End If
  Next
  Application.ScreenUpdating = True
  v_Rst.Close
  v_Cnn.Close
  Set v_Rst = Nothing
  Set v_Cnn = Nothing
  Set v_FSO = Nothing
End Sub

Примечание:
  • По умолчанию и для Jet OLEDB Provider (Jet) и для OLEDB Provider for ODBC Drivers (ODBC)
    подразумевается, что первая строка Excel’евских данных содержит заголовки столбцов (полей) (для Jet этому соответствует параметр HDR=Yes; для ODBC параметр FirstRowHasNames=1). По условию данные надо извлечь из первой строки листа (ячейка A1). Для ODBC установка параметра FirstRowHasNames в 0 (False) из-за http://support.microsoft.com/kb/288343/EN-US/ ничего не дает, поэтому использован Jet провайдер с параметром HDR=No.
  • Вставка данных в ячейки листа осуществляется с помощью метода CopyFromRecordset, и соответственно обращение к листу происходит на каждом шаге цикла. Попытка использовать метод GetRows объекта Recordset (т.е. добавлять данные из Recordset в массив, а затем разом вставить содержимое массива в лист Excel, например, так:
    Код
    Range(Cells(1, 1), Cells(v_FileCount, 1)) = v_TmpArray()

    на удивление сколь нибудь заметного выигрыша в производительности не дала, поэтому этот вариант не привожу.
  • Использование раннего связывания (речь идет об объектах FileSystemObject, Connection и Recordset) также не приводит к ощутимому ускорению процесса.
  • Подразумевалось, что имя листа в книгах, откуда берутся данные – "Лист1".
Если за 100% принять среднее время работы s_Test_1, то для s_Test_2 это время составило около 5,6% (т.е. второй вариант отрабатывает примерно в 20 раз быстрее).

Автор: Naghual 28.11.2006, 10:44
Aloha, вами проделана значительная работа. 
Предлагаю вам поместить это в ФАК.

Автор: Йекс 28.11.2006, 13:11
Aloha

Просто преогромнейшее спасибо. Чесно говоря, я совершенно не понял, как это в Вашем втором методе всё происходит, но работает это действительно превосходно. Методом научного тыка до меня дошло, как копировать не только ячейку а1, но и сразу с десяток необходимых мне ячеек  (расположенных на разных листах и в разных частях документа). По скорости действительно не сравнить с тем, что у меня было...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)