2016-12-20 6 views
0

Основой этого проекта является предоставление портала ввода данных, расположенного на сайте Shrepoint. Менеджеры будут вводить ожидаемый спрос сотрудников на каждую функцию задания, и программа будет сопоставлять эти данные с легко читаемыми графами и метриками.Альтернатива очень медленному vba vlookup для закрытых сетевых файлов

Таблицы ввода данных подаются на вкладку «Общий спрос» в каждой книге проектов, но это не моя проблема. Моя проблема заключается в том, чтобы поднять данные из этих листов «Общий спрос» (по одному для каждой рабочей книги проекта) в основную книгу с аналогичным форматом.

Эти листы предназначены как можно более автоматизированы и ориентированы на пользователей, не имеющих особого характера, с чем-то более сложным, чем функция SUM(). По этой причине я хотел бы сохранить листы проектов закрытыми, пока данные считываются из них.

Код в основной книге В настоящее время у меня есть подпрограмма для форматирования отчета с правильными датами и проектами, затем он проходит каждую строку до тех пор, пока не найдет строку, требующую данных. Отсюда он использует функцию GetValue (найденную здесь: http://spreadsheetpage.com/index.php/tip/a_vba_function_to_get_a_value_from_a_closed_file/), чтобы поднять данные, такие как первый месяц с данными, из отдельных отчетов.

Затем он перебирает столбцы, записывая формулу в каждую ячейку, чтобы найти значения, найденные в отчетах. Я включил приведенную ниже версию этого кода ниже.

job = Cells(rowindexA, 1).Value 
targetSheetArray = "'" & path & "[" & file & "]" & ws & "'!" & Range(Cells(1, 2), Cells(100, 100)).Address(, , xlR1C1) 

For ColIndex = 10 To numMonths + 9 

    targetSheetColumn = ColIndex + monthsDif 

    'This formula works but is incredibly slow (multiple seconds PER ENTRY) 
    Cells(rowindexA + rowindexB, ColIndex).Formula = "=VLookup(" & Chr(34) & job & Chr(34) & "," & targetSheetArray & "," & targetSheetColumn & ",FALSE)" 

    'This formula was from a similar idea than the one above, but Application.WorksheetFunction doesn't work on closed sheets 
    'Cells(rowindexA + rowindexB, ColIndex).Value = Application.WorksheetFunction.VLookup(job, targetSheetArray, targetSheetColumn, False)       

Next 

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

Я хотел бы найти способ, который запрещает макросу вычислять значение поиска до самого конца, после чего он может сразу считывать все данные. Я пробовал

Application.Calculation = xlCalculationManual 

но это, похоже, не влияет на процедуру VLookup, поэтому я не уверен, что это возможно.

Я также играл с идеей о том, чтобы макрос открывал рабочие книги проекта, копировал данные, а затем закрывал их снова, но это кажется слишком громоздким и ненадежным, хотя я не сомневаюсь, что это будет быстрее.

Есть ли у кого-нибудь предложения?

+0

«По этой причине я хотел бы сохранить листы проектов закрытыми, пока данные считываются из них». В чем преимущество этого? Лучше всего перебирать каждый файл и вытаскивать все данные локально и делать какие-либо вычисления оттуда. –

ответ

0

Да, есть более быстрый путь, чем использование VLookup.

Используйте вместо этого вложенную петлю (цикл по строкам в ws). Если возможно, заключите вложенный цикл в оператор if (не уверен в том, как вы сформулировали свой вопрос, если он применим к вашей проблеме). Он все еще O (n^2), но петли быстрее, чем VLookup.

Возможно, существует еще лучший способ. В зависимости от структуры данных, которые вы сравниваете (рабочий лист, на котором вы запускаете макрос, и рабочий лист, который является источником данных VLookup), вы можете сначала отсортировать листы (на основе общего ключа), а затем запустить вложенная петля с операторами типа continue, использующими GoTo. Пример:

Dim ws As Worksheet, compared As Worksheet 
Dim i As Integer, j As Integer 
j = 1 

For i = 1 to wsLastrow 
    While j <= comparedLastrow 
     j = j + 1 
     If ws.cells(i, relevantColumn) = compared(j, someColumn) Then 
      ws.cells(i, targetColumn) = someValue 'from row j in compared worksheet 
      GoTo Continue 
     End If 
    Wend 
Continue: 
Next