Для передачи данных между приложениями, т.к. необходимые объёмы совсем небольшие (массивы из нескольких коротких стрингов), решил попробовать заюзать переменные окружения Windows Погуглил, поковырялся в процедурах. Оказывается, это совсем не сложно. Единственно, что мне не понятно - относительно большое и абсолютно не предсказуемое время создания-чтения-удаления пользовательской переменной окружения. Для тестирования написал процедурку:
Мало того, что длительности достаточно велики (но для моих целей это не очень критично), но от теста к тесту они ещё и существенно разные. А Длительность чтения вообще иногда показывается отрицательной!
---------- тест 1 ------------
Create Duration = 0,1953125 s
Environment("USER").Count = 5
Read Duration = 0,197265625 s Value = test-test-test
Delete Duration = 0,27734375 s
Environment("USER").Count = 4
---------- тест 2 ------------
Environment("USER").Count = 4
Create Duration = 0,796875 s
Environment("USER").Count = 5
Read Duration = -0,201171875 s Value = test-test-test
Delete Duration = 1,900390625 s
Environment("USER").Count = 4
Такое впечатление, что при передаче управления объекту WScript.Shell таймер не только останавливается, но иногда ещё и отматывается обратно. Это как?
Для передачи данных между приложениями, т.к. необходимые объёмы совсем небольшие (массивы из нескольких коротких стрингов), решил попробовать заюзать переменные окружения Windows Погуглил, поковырялся в процедурах. Оказывается, это совсем не сложно. Единственно, что мне не понятно - относительно большое и абсолютно не предсказуемое время создания-чтения-удаления пользовательской переменной окружения. Для тестирования написал процедурку:
Мало того, что длительности достаточно велики (но для моих целей это не очень критично), но от теста к тесту они ещё и существенно разные. А Длительность чтения вообще иногда показывается отрицательной!
---------- тест 1 ------------
Create Duration = 0,1953125 s
Environment("USER").Count = 5
Read Duration = 0,197265625 s Value = test-test-test
Delete Duration = 0,27734375 s
Environment("USER").Count = 4
---------- тест 2 ------------
Environment("USER").Count = 4
Create Duration = 0,796875 s
Environment("USER").Count = 5
Read Duration = -0,201171875 s Value = test-test-test
Delete Duration = 1,900390625 s
Environment("USER").Count = 4
Такое впечатление, что при передаче управления объекту WScript.Shell таймер не только останавливается, но иногда ещё и отматывается обратно. Это как? Alex_ST
С уважением, Алексей MS Excel 2003 - the best!!!
Сообщение отредактировал Alex_ST - Вторник, 29.11.2016, 09:21
Проверил с системным таймером через GetTickCount ( с возможностью VBA7 And Win64 заморачиваться не стал, т.к. у меня это не бывает никогда) Непонятно, почему время разное получается? И, таки-да, нулевое время реально напрягает К стати, Евгений, в зачем ты добавил - в Debug.Print перед системным таймером? Не понял, поэтому убрал, чтобы глаз не мозолило.
Environment("USER").Count = 4
Create Duration = 1,5703125 s 1,092s
Environment("USER").Count = 5
Read Duration = -0,4296875 s Value = test-test-test 0s
Delete Duration = 1,65625 s 2,075s
Environment("USER").Count = 4
Проверил с системным таймером через GetTickCount ( с возможностью VBA7 And Win64 заморачиваться не стал, т.к. у меня это не бывает никогда) Непонятно, почему время разное получается? И, таки-да, нулевое время реально напрягает К стати, Евгений, в зачем ты добавил - в Debug.Print перед системным таймером? Не понял, поэтому убрал, чтобы глаз не мозолило.
Environment("USER").Count = 4
Create Duration = 1,5703125 s 1,092s
Environment("USER").Count = 5
Read Duration = -0,4296875 s Value = test-test-test 0s
Delete Duration = 1,65625 s 2,075s
Environment("USER").Count = 4
Но вообще-то, поковырявшись, много нового узнал о работе с переменными окружения. Например, то, что есть разные типы, но для самостоятельного использования доступны только переменные типа User Также то, что имена переменных уникальны только внутри типа. В общем, слепил процедурку, которая на лист выводит перечень всех переменных окружения, их типы и значения. Может быть кому-нибудь пригодится:
Sub ENVIROMENTS_Excel_Sheet() ' создать в текущей книге лист со списоком переменных окружения, их типами и значениями ' On Error Resume Next Dim oSheet As Worksheet, sEnvName$, sEnvVal$, xArr, xItem, iNdex% Dim sHeader(): sHeader = Array("Environment Name", "Environment Type", "Environment Value (at this computer)") Dim Arr(): Arr = Array("SYSTEM", "VOLATILE", "PROCESS", "USER") ' все возможные типы переменных окружения Dim oDict: Set oDict = CreateObject("Scripting.Dictionary"): oDict.CompareMode = vbTextCompare ' словарь для сбора данных Dim oShell: Set oShell = CreateObject("WScript.Shell") ' ссылка на объект WScript.Shell
iNdex = iNdex + 1' т.к. sEnvName не уникальны и могут повторяться в разных типах, то как ключ приходится использовать iNdex
oDict.Add Key:=iNdex, Item:=Array(sHeader(0), sHeader(1), sHeader(2)) ' заголовки таблицы 'Debug.Print iNdex & vbTab & oDict.Item(iNdex)(0) & vbTab & oDict.Item(iNdex)(1) & vbTab & oDict.Item(iNdex)(2) For Each xArr In Arr ' цикл по всем типам переменных For Each xItem In oShell.Environment(xArr) ' цикл по всем переменным данного типа
sEnvName = Left(xItem, 1) & Split(Mid(xItem, 2), "=")(0)
sEnvName = IIf(Left(sEnvName, 1) = "=", "'", "") & sEnvName ' патч для предотвращения вычисления формул на листе Excel
sEnvVal = Split(Mid(xItem, 2), "=", 2)(1)
sEnvVal = IIf(Left(sEnvVal, 1) = "=", "'", "") & sEnvVal ' патч для предотвращения вычисления формул на листе Excel
iNdex = iNdex + 1
oDict.Add Key:=iNdex, Item:=Array(sEnvName, xArr, sEnvVal) 'Debug.Print iNdex & vbTab & oDict.Item(iNdex)(0) & vbTab & oDict.Item(iNdex)(1) & vbTab & oDict.Item(iNdex)(2) Next xItem Next xArr With Application.WorksheetFunction ' функция листа ТРАНСП при транспонировании преобразует массив массивов в 2D-массив
Arr = .Transpose(.Transpose(oDict.Items)) EndWith
Application.ScreenUpdating = False: Application.EnableEvents = False Set oSheet = ThisWorkbook.Worksheets.Add
Cells(1, 1).Resize(UBound(Arr, 1), UBound(Arr, 2)).Value = Arr ' массив - на лист
Rows("2:2").Select: ActiveWindow.FreezePanes = True: Rows("1:1").Font.Bold = True' красота на листе With Cells: .EntireColumn.AutoFit: .HorizontalAlignment = xlLeft: .VerticalAlignment = xlBottom: EndWith
Application.ScreenUpdating = True: Application.EnableEvents = True EndSub
Но вообще-то, поковырявшись, много нового узнал о работе с переменными окружения. Например, то, что есть разные типы, но для самостоятельного использования доступны только переменные типа User Также то, что имена переменных уникальны только внутри типа. В общем, слепил процедурку, которая на лист выводит перечень всех переменных окружения, их типы и значения. Может быть кому-нибудь пригодится:
Sub ENVIROMENTS_Excel_Sheet() ' создать в текущей книге лист со списоком переменных окружения, их типами и значениями ' On Error Resume Next Dim oSheet As Worksheet, sEnvName$, sEnvVal$, xArr, xItem, iNdex% Dim sHeader(): sHeader = Array("Environment Name", "Environment Type", "Environment Value (at this computer)") Dim Arr(): Arr = Array("SYSTEM", "VOLATILE", "PROCESS", "USER") ' все возможные типы переменных окружения Dim oDict: Set oDict = CreateObject("Scripting.Dictionary"): oDict.CompareMode = vbTextCompare ' словарь для сбора данных Dim oShell: Set oShell = CreateObject("WScript.Shell") ' ссылка на объект WScript.Shell
iNdex = iNdex + 1' т.к. sEnvName не уникальны и могут повторяться в разных типах, то как ключ приходится использовать iNdex
oDict.Add Key:=iNdex, Item:=Array(sHeader(0), sHeader(1), sHeader(2)) ' заголовки таблицы 'Debug.Print iNdex & vbTab & oDict.Item(iNdex)(0) & vbTab & oDict.Item(iNdex)(1) & vbTab & oDict.Item(iNdex)(2) For Each xArr In Arr ' цикл по всем типам переменных For Each xItem In oShell.Environment(xArr) ' цикл по всем переменным данного типа
sEnvName = Left(xItem, 1) & Split(Mid(xItem, 2), "=")(0)
sEnvName = IIf(Left(sEnvName, 1) = "=", "'", "") & sEnvName ' патч для предотвращения вычисления формул на листе Excel
sEnvVal = Split(Mid(xItem, 2), "=", 2)(1)
sEnvVal = IIf(Left(sEnvVal, 1) = "=", "'", "") & sEnvVal ' патч для предотвращения вычисления формул на листе Excel
iNdex = iNdex + 1
oDict.Add Key:=iNdex, Item:=Array(sEnvName, xArr, sEnvVal) 'Debug.Print iNdex & vbTab & oDict.Item(iNdex)(0) & vbTab & oDict.Item(iNdex)(1) & vbTab & oDict.Item(iNdex)(2) Next xItem Next xArr With Application.WorksheetFunction ' функция листа ТРАНСП при транспонировании преобразует массив массивов в 2D-массив
Arr = .Transpose(.Transpose(oDict.Items)) EndWith
Application.ScreenUpdating = False: Application.EnableEvents = False Set oSheet = ThisWorkbook.Worksheets.Add
Cells(1, 1).Resize(UBound(Arr, 1), UBound(Arr, 2)).Value = Arr ' массив - на лист
Rows("2:2").Select: ActiveWindow.FreezePanes = True: Rows("1:1").Font.Bold = True' красота на листе With Cells: .EntireColumn.AutoFit: .HorizontalAlignment = xlLeft: .VerticalAlignment = xlBottom: EndWith
Application.ScreenUpdating = True: Application.EnableEvents = True EndSub
А сколько переменных выводит Environ и сколько CreateObject("WScript.Shell").Environment(sEnvType) Вы видели? Да и, как правильно сказал Udik, Environ только читает переменные. Это я и сам давно выяснил, потому и закопался в Environment Но вопрос со странным временем работы с Environment так и остался открытым...
А сколько переменных выводит Environ и сколько CreateObject("WScript.Shell").Environment(sEnvType) Вы видели? Да и, как правильно сказал Udik, Environ только читает переменные. Это я и сам давно выяснил, потому и закопался в Environment Но вопрос со странным временем работы с Environment так и остался открытым...Alex_ST
С уважением, Алексей MS Excel 2003 - the best!!!
Сообщение отредактировал Alex_ST - Вторник, 29.11.2016, 22:10
А феномен отрицательного времени по таймеру мне на Планете объяснили: я, оказывается лоханулся и значение, получаемое от Timer запихивал в переменную Long вместо Single Вот при округлении близкого к нулю значения лажа и получалась.
А феномен отрицательного времени по таймеру мне на Планете объяснили: я, оказывается лоханулся и значение, получаемое от Timer запихивал в переменную Long вместо Single Вот при округлении близкого к нулю значения лажа и получалась.Alex_ST
Udik, попробовал я-таки твой пример с API-шным обращением. Скорость, конечно, впечатляет. И то, что переменные создаются процессные (PROCESS), а не пользовательские (USER), а потому их нет необходимости удалять, т.к. сами умирают после перезапуска Excel - это отлично. Но до чего же не люблю я API Их в отличие от VBA запомнить невозможно, а нужно тупо как иероглифы из справочника дёргать. Да и процедуры с их использованием получаются размазанными по всему модулю: сама процедура в одном месте листинга, а API-шки для неё - в декларациях. Копирнёшь куда-нибудь процедуру, а про декларации забудешь...
Udik, попробовал я-таки твой пример с API-шным обращением. Скорость, конечно, впечатляет. И то, что переменные создаются процессные (PROCESS), а не пользовательские (USER), а потому их нет необходимости удалять, т.к. сами умирают после перезапуска Excel - это отлично. Но до чего же не люблю я API Их в отличие от VBA запомнить невозможно, а нужно тупо как иероглифы из справочника дёргать. Да и процедуры с их использованием получаются размазанными по всему модулю: сама процедура в одном месте листинга, а API-шки для неё - в декларациях. Копирнёшь куда-нибудь процедуру, а про декларации забудешь...Alex_ST