Вот метод, который, я знаю, будет работать. Однако есть некоторые осложнения.
Вот как это делается:
- Поместите электронную таблицу с данными в отдельную рабочую книгу. Этот лист должен выполнить запрос на обновление при открытии, а затем закрыть после обновления данных.
- Создайте командный файл для вызова файла Excel «Данные».
- В другой рабочей книге создайте процедуру (макрос) для вызова пользователем. Эта процедура вызывает пакетный файл, который впоследствии вызывает файл Excel. Поскольку вы вызываете командный файл, а не Excel, процедура Excel будет продолжена, потому что командная оболочка запускается так быстро и открывает другой файл Excel в другом потоке. Это позволяет продолжить работу в основном файле Excel.
Вот некоторые осложнения:
- Я включил метод предупреждения пользователя об обновлении данных. Существуют проблемы с синхронизацией, когда можно попытаться проверить, обновлялись ли данные, когда рабочая книга недоступна, что вынуждает пользователя пытаться обновить значения. Я включил метод под названием «мое время», который приостанавливает выполнение кода, поэтому он проверяет только каждые столько секунд.
- Обновленная рабочая таблица появится в новом окне, поэтому пользователю нужно будет щелкнуть ее исходную рабочую таблицу и продолжить работу. Вы могли бы научиться скрывать это, если вы знакомы со сценариями Windows (я этого еще не узнал).
Вот некоторые файлы и код. Обязательно прочитайте комментарии в коде, чтобы узнать, почему некоторые вещи есть.
ФАЙЛ: C: \ DataUpdate.xls
Мы создадим рабочую книгу с именем «DataUpdate.xls» и поместим ее в нашу папку C: \. В ячейку A1 листа Sheet1 мы добавим таблицу QueryTable, которая получает внешние данные.
Option Explicit
Sub UpdateTable()
Dim ws As Worksheet
Dim qt As QueryTable
Set ws = Worksheets("Sheet1")
Set qt = ws.Range("A1").QueryTable
qt.Refresh BackgroundQuery:=False
End Sub
Sub OnWorkbookOpen()
Dim wb As Workbook
Set wb = ActiveWorkbook
'I put this If statement in so I can change the file's
'name and then edit the file without code
'running. You may find a better way to do this.
If ActiveWorkbook.Name = "DataUpdate.xls" Then
UpdateTable
'I update a cell in a different sheet once the update is completed.
'I'll check this cell from the "user workbook" to see when the data's been updated.
Sheets("Sheet2").Range("A1").Value = "Update Table Completed " & Now()
wb.Save
Application.Quit
End If
End Sub
В объекте ThisWorkbook
в Excel есть процедура Workbook_Open (). Он должен выглядеть следующим образом, чтобы при запуске он выполнял код обновления.
Private Sub Workbook_Open()
OnWorkbookOpen
End Sub
ПРИМЕЧАНИЕ. Я обнаружил ошибку при закрытии этого файла, если 1) вы получили доступ к файлу из командной строки или оболочки и 2) у вас установлена надстройка Office Live. Если у вас установлена надстройка Office Live, при выходе она выдаст исключение.
ФАЙЛ: C: \ RunExcel.bat
Далее мы собираемся создать командный файл, который откроет файл Excel, который мы только что создали. Причина, по которой файл Excel вызывается из пакетного файла, а не напрямую из другого файла Excel с помощью Shell, заключается в том, что Shell не продолжит работу, пока не закроется другое приложение (по крайней мере, при использовании Excel.exe "c:\File.xls"
). Пакетный файл, однако, запускает свой код и затем немедленно закрывается, что позволяет исходному коду, который его вызвал, продолжить. Это то, что позволит вашим приложениям продолжать работать в Excel.
Все, что нужно для этого файла:
cd "C:\Program Files\Microsoft Office\Office10\"
Excel.exe "C:\DataUpdate.xls"
Если вам удобно использовать Windows Scripting, вы делаете такие вещи, как открытие окна в скрытом режиме или передача параметра имени файла или местоположения Excel. Я держал это простым с командным файлом.
ФАЙЛ: C: \ UserWorkbook.xls
Это файл, который пользователь откроет, чтобы «выполнить свою работу». Они будут вызывать код для обновления другой рабочей книги из этой рабочей книги, и они по-прежнему смогут работать с этой рабочей книгой, пока обновляется эта.
Вам нужна ячейка в этой книге, в которой вы проверите ячейку «Обновление таблицы завершено» из книги DataUpdate. Я выбрал ячейку G1 в Sheet1 для моего примера.
Добавьте следующий код в модуль VBA в этой книге:
Option Explicit
Sub UpdateOtherWorkbook()
Dim strFilePath As String
Dim intOpenMode As Integer
Dim strCallPath As String
Dim strCellValue As String
Dim strCellFormula As String
Dim ws As Worksheet
Dim rng As Range
Set ws = Worksheets("Sheet1")
Set rng = ws.Range("G1")
strCellFormula = "='C:\[DataUpdate.xls]Sheet2'!A1"
'This makes sure the formula has the most recent "Updated" value
'from the data file.
rng.Formula = strCellFormula
strFilePath = "C:\RunExcel.bat"
intOpenMode = vbHide
'This will call the batch file that calls the Excel file.
'Since the batch file executes it's code and then closes,
'the Excel file will be able to keep running.
Shell strFilePath, intOpenMode
'This method, defined below, will alert the user with a
'message box once the update is complete. We know that
'the update is complete because the "Updated" value will
'have changed in the Data workbook.
AlertWhenChanged
End Sub
Sub AlertWhenChanged()
Dim strCellValue As String
Dim strUpdatedCellValue As String
Dim strCellFormula As String
Dim ws As Worksheet
Dim rng As Range
Set ws = Worksheets("Sheet1")
Set rng = ws.Range("G1")
strCellFormula = "='C:\[DataUpdate.xls]Sheet2'!A1"
strCellValue = rng.Value
strUpdatedCellValue = strCellValue
'This will check every 4 seconds to see if the Update value of the
'Data workbook has been changed. MyWait is included to make sure
'we don't try to access the Data file while it is inaccessible.
'During this entire process, the user is still able to work.
Do While strCellValue = strUpdatedCellValue
MyWait 2
rng.Formula = strCellFormula
MyWait 2
strUpdatedCellValue = rng.Value
DoEvents
Loop
MsgBox "Data Has Been Updated!"
End Sub
Sub MyWait(lngSeconds As Long)
Dim dtmNewTime As Date
dtmNewTime = DateAdd("s", lngSeconds, Now)
Do While Now < dtmNewTime
DoEvents
Loop
End Sub
Как видите, я постоянно обновлял формулу в "ячейке прослушивания", чтобы видеть, когда обновлялась другая ячейка. После того, как рабочая книга данных была обновлена, я не уверен, как бы вы принудительно обновили код, не переписав все ячейки. Закрытие книги и ее повторное открытие должны обновить значения, но я не уверен, что это лучший способ сделать это в коде.
Весь этот процесс работает, потому что вы используете пакетный файл для вызова Excel в другой поток из исходного файла. Это позволяет вам работать с исходным файлом и получать уведомления при обновлении другого файла.
Удачи!