Всем здравствуйте! Наконец-то зарегистрировался на этом продвинутом форуме. Тут есть отдельный раздел "готовых решений" и даже "мозговой штурм", такое есть, конечно далеко не везде, это круто и наверное очень удобно. И, главное этот форум посвящен Экселю, по которому у меня последнее время назрел один вопрос-не вопрос, который наверное подходит под характер данного раздела, хотя, это конечно не готовое решение, и я даже не знаю на сколько полезное, в этом бы хотелось разобраться. Кто-нибудь что-нибудь слышал про использование С-API Excel в VBA, я не слышал, поэому для меня, когда я это обнаружил, было новостью, что это возможно использовать при чем без каких-то особенных переходников, что называется "на-прямую". Предполагаемая польза, как я думаю, может быть в бОльшей скорости вывода информации на лист, но я это не проверял, а пока лишь разбирался в способах взаимодействия с этим API. Во-первых стоит сказать спасибо человеку, автору одного замечательного проекта, надо отдать должное, проделана большая работа. Я уже просматривал, что-то немножко дополнял, компилировал, действительно создается рабочая xll-ка. Но чуть позже я решил копнуть чуть глубже в суть его работы, и обнаружил, что это может работать и в VBA, коненчо со многими оговорками. UDF-ку из vba в API не зарегистриуешь конечно.. хотя, кто его знает, может быть есть какие-то лазейки, другой врпрос, конечно, зачем.. Во вложенииПо ссылке данный проект, немного доработанный под vba и некоторые примеры использования, из того-что я уже изучил. В дальнейшем я возможно буду еще что-то дополнять, просто самому интересно, есть там что-нибудь такое конкретное, чего нет в vba/com. На глаза попадались, допустим, функции битового сдвига. И, возможно, если кому-то будет это интересно, также дополнит тему какими-то примерами.
Всем здравствуйте! Наконец-то зарегистрировался на этом продвинутом форуме. Тут есть отдельный раздел "готовых решений" и даже "мозговой штурм", такое есть, конечно далеко не везде, это круто и наверное очень удобно. И, главное этот форум посвящен Экселю, по которому у меня последнее время назрел один вопрос-не вопрос, который наверное подходит под характер данного раздела, хотя, это конечно не готовое решение, и я даже не знаю на сколько полезное, в этом бы хотелось разобраться. Кто-нибудь что-нибудь слышал про использование С-API Excel в VBA, я не слышал, поэому для меня, когда я это обнаружил, было новостью, что это возможно использовать при чем без каких-то особенных переходников, что называется "на-прямую". Предполагаемая польза, как я думаю, может быть в бОльшей скорости вывода информации на лист, но я это не проверял, а пока лишь разбирался в способах взаимодействия с этим API. Во-первых стоит сказать спасибо человеку, автору одного замечательного проекта, надо отдать должное, проделана большая работа. Я уже просматривал, что-то немножко дополнял, компилировал, действительно создается рабочая xll-ка. Но чуть позже я решил копнуть чуть глубже в суть его работы, и обнаружил, что это может работать и в VBA, коненчо со многими оговорками. UDF-ку из vba в API не зарегистриуешь конечно.. хотя, кто его знает, может быть есть какие-то лазейки, другой врпрос, конечно, зачем.. Во вложенииПо ссылке данный проект, немного доработанный под vba и некоторые примеры использования, из того-что я уже изучил. В дальнейшем я возможно буду еще что-то дополнять, просто самому интересно, есть там что-нибудь такое конкретное, чего нет в vba/com. На глаза попадались, допустим, функции битового сдвига. И, возможно, если кому-то будет это интересно, также дополнит тему какими-то примерами.testuser2
Вывод 200 000 строк на лист. Примерно все одинаково [vba]
Код
Private Sub TestSpeed2() Const maxCnt = 200000 Static blInit As Boolean, sRndAr$() Dim xSRef As XL12SRef Dim i&, t1!, t2!, lRet As Excel4ReturnCodes Dim vAr$(), xStrAr() As XL12Str
If blInit Then Else sRndAr = GetRndStrArray(maxCnt, 5, 10): blInit = True
ReDim vAr(maxCnt - 1, 0) ReDim xStrAr(maxCnt - 1)
t1 = Timer For i = 0 To maxCnt - 1 With xStrAr(i) .xltype = xltypeStr .Str = ChrW(Len(sRndAr(i))) & sRndAr(i) End With Next lRet = MdCallBack12(xlfIndirect, 1, TempStr12p("B1:B" & maxCnt), xSRef) lRet = Excel12p(xlSet, 0, 2, VarPtr(xSRef), TempMulti12p(maxCnt, 1, VarPtr(xStrAr(0)))) t1 = Timer - t1
t2 = Timer For i = 0 To maxCnt - 1 vAr(i, 0) = sRndAr(i) Next Range("C1:C" & maxCnt).value = vAr t2 = Timer - t2
Debug.Print t1, t2 Stop columns(2).Resize(, 2).Clear End Sub
Function GetRndStrArray(ByVal cnt As Long, ByVal minStrSz&, ByVal maxStrSz&) As String() cnt = cnt - 1 Dim i&, sArOut$(): ReDim sArOut(cnt) For i = 0 To cnt sArOut(i) = GetRandomString(minStrSz, maxStrSz) Next GetRndStrArray = sArOut End Function Function GetRandomString(ByVal Lw&, ByVal Up&) As String Static init As Boolean, ChrTbl$, ChrTblLen& If init Then Else ChrTbl = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqastuvwxyzАБВГДЕЁЖЗИЙКЛМНУФХЦЧШЩЬЫЪЭЮЯабвгдеёжзийклмнопрстуфхцчшщьыъэюя " ChrTblLen = Len(ChrTbl) Randomize init = True End If Dim i&, j&, strLen&: strLen = (Up - Lw + 1) * Rnd + Lw GetRandomString = String(strLen, vbNullChar) For i = 1 To strLen j = Int(ChrTblLen * Rnd + 1) Mid$(GetRandomString, i) = Mid$(ChrTbl, j, 1) Next End Function
[/vba]
Вывод 200 000 строк на лист. Примерно все одинаково [vba]
Код
Private Sub TestSpeed2() Const maxCnt = 200000 Static blInit As Boolean, sRndAr$() Dim xSRef As XL12SRef Dim i&, t1!, t2!, lRet As Excel4ReturnCodes Dim vAr$(), xStrAr() As XL12Str
If blInit Then Else sRndAr = GetRndStrArray(maxCnt, 5, 10): blInit = True
ReDim vAr(maxCnt - 1, 0) ReDim xStrAr(maxCnt - 1)
t1 = Timer For i = 0 To maxCnt - 1 With xStrAr(i) .xltype = xltypeStr .Str = ChrW(Len(sRndAr(i))) & sRndAr(i) End With Next lRet = MdCallBack12(xlfIndirect, 1, TempStr12p("B1:B" & maxCnt), xSRef) lRet = Excel12p(xlSet, 0, 2, VarPtr(xSRef), TempMulti12p(maxCnt, 1, VarPtr(xStrAr(0)))) t1 = Timer - t1
t2 = Timer For i = 0 To maxCnt - 1 vAr(i, 0) = sRndAr(i) Next Range("C1:C" & maxCnt).value = vAr t2 = Timer - t2
Debug.Print t1, t2 Stop columns(2).Resize(, 2).Clear End Sub
Function GetRndStrArray(ByVal cnt As Long, ByVal minStrSz&, ByVal maxStrSz&) As String() cnt = cnt - 1 Dim i&, sArOut$(): ReDim sArOut(cnt) For i = 0 To cnt sArOut(i) = GetRandomString(minStrSz, maxStrSz) Next GetRndStrArray = sArOut End Function Function GetRandomString(ByVal Lw&, ByVal Up&) As String Static init As Boolean, ChrTbl$, ChrTblLen& If init Then Else ChrTbl = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqastuvwxyzАБВГДЕЁЖЗИЙКЛМНУФХЦЧШЩЬЫЪЭЮЯабвгдеёжзийклмнопрстуфхцчшщьыъэюя " ChrTblLen = Len(ChrTbl) Randomize init = True End If Dim i&, j&, strLen&: strLen = (Up - Lw + 1) * Rnd + Lw GetRandomString = String(strLen, vbNullChar) For i = 1 To strLen j = Int(ChrTblLen * Rnd + 1) Mid$(GetRandomString, i) = Mid$(ChrTbl, j, 1) Next End Function
В API Экселя есть возможность сохранять бинарные данные в структуре документа. К слову сказать, в vba также присутствует недокументированная возможность сохранять бинарные данные, как ее использовать описал Виталий (btedVit) на другом форуме. Так выглядит работа с бин. данными из API [vba]
Код
Private Sub TestBIGDATA() Dim xData As XL12BigData, bData() As Byte, lRet As Excel4ReturnCodes Dim bFile() As Byte, xName As XL12Str, lp As LongPtr
В API Экселя есть возможность сохранять бинарные данные в структуре документа. К слову сказать, в vba также присутствует недокументированная возможность сохранять бинарные данные, как ее использовать описал Виталий (btedVit) на другом форуме. Так выглядит работа с бин. данными из API [vba]
Код
Private Sub TestBIGDATA() Dim xData As XL12BigData, bData() As Byte, lRet As Excel4ReturnCodes Dim bFile() As Byte, xName As XL12Str, lp As LongPtr
А так можно получить уникальный идентификатор листа. [vba]
Код
Function GetSheetID(sShName$) As LongPtr Dim xRef As XL12Ref If MdCallBack12(xlsheetid, 1, TempStr12p(sShName), xRef) = xlretSuccess Then GetSheetID = xRef.idSheet End If End Function
[/vba] Мне было интересно узнать, является ли этот идентификатор просто числом, или может быть это указатель, и мой интерес оправдался, это оказалось указателем на участок памяти, в котором по определенному смещению были найдены еще 2 интересных указателя, которые напрямую связаны к доступу ячейкам в памяти на прямую. Дело в том, что я недавно довольно плотно исследовал вопрос прямого доступа к ячейкам в памяти и уже придумал как находить те указатели но не очень безопасным методом, а тут я обнаружил, считай, прямой и безопасный доступ к этим указателям, поэтому можно обновить алгоритм. Однако же стоит сказать пару слов об этом прямом доступе, из проведенных мной тестов, этот прямой доступ не дает какого-то особенного преимущество в скорости чтения по сравнению с обычным получением данных из метода Range.Value.
А так можно получить уникальный идентификатор листа. [vba]
Код
Function GetSheetID(sShName$) As LongPtr Dim xRef As XL12Ref If MdCallBack12(xlsheetid, 1, TempStr12p(sShName), xRef) = xlretSuccess Then GetSheetID = xRef.idSheet End If End Function
[/vba] Мне было интересно узнать, является ли этот идентификатор просто числом, или может быть это указатель, и мой интерес оправдался, это оказалось указателем на участок памяти, в котором по определенному смещению были найдены еще 2 интересных указателя, которые напрямую связаны к доступу ячейкам в памяти на прямую. Дело в том, что я недавно довольно плотно исследовал вопрос прямого доступа к ячейкам в памяти и уже придумал как находить те указатели но не очень безопасным методом, а тут я обнаружил, считай, прямой и безопасный доступ к этим указателям, поэтому можно обновить алгоритм. Однако же стоит сказать пару слов об этом прямом доступе, из проведенных мной тестов, этот прямой доступ не дает какого-то особенного преимущество в скорости чтения по сравнению с обычным получением данных из метода Range.Value.testuser2
Сообщение отредактировал testuser2 - Пятница, 02.05.2025, 10:58