Домашняя страница Undo Do New Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/Excel API в VBA - Мир MS Excel

  • Страница 1 из 1
  • 1
Модератор форума: _Boroda_, китин, DrMini  
Excel API в VBA
testuser2 Дата: Среда, 30.04.2025, 16:41 | Сообщение № 1
Группа: Пользователи
Ранг: Новичок
Сообщений: 12
Репутация: 4 ±
Замечаний: 0% ±

2019
Всем здравствуйте! Наконец-то зарегистрировался на этом продвинутом форуме. Тут есть отдельный раздел "готовых решений" и даже "мозговой штурм", такое есть, конечно далеко не везде, это круто и наверное очень удобно. И, главное этот форум посвящен Экселю, по которому у меня последнее время назрел один вопрос-не вопрос, который наверное подходит под характер данного раздела, хотя, это конечно не готовое решение, и я даже не знаю на сколько полезное, в этом бы хотелось разобраться.
Кто-нибудь что-нибудь слышал про использование С-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
Дата добавления - 30.04.2025 в 16:41
testuser2 Дата: Четверг, 01.05.2025, 10:33 | Сообщение № 2
Группа: Пользователи
Ранг: Новичок
Сообщений: 12
Репутация: 4 ±
Замечаний: 0% ±

2019
Вывод значения в одну и ту же ячейку, ни какой разницы в скорости, Api vs Com
[vba]
Код
Sub TestSpeed()
    Dim lRet As Excel4ReturnCodes
    Dim xNum As XL12Num, xRef As XL12Ref
    Dim xSRef As XL12SRef, i#, t1!, t2!
    Dim d#, oCell As Range
        
    MdCallBack12 xlfIndirect, 1, TempStr12p("B8"), xSRef
    Set oCell = Range("B6")
    
    xNum.xltype = xltypeNum
    t1 = Timer
    For xNum.dVal = 1# To 30000#
        Excel12p xlSet, 0, 2, VarPtr(xSRef), VarPtr(xNum)
    Next
    t1 = Timer - t1
    
    t2 = Timer
    For d = 1# To 30000#
        oCell.value = d
    Next
    t2 = Timer - t2
    
    Debug.Print t1, t2
End Sub
[/vba]
Результат
2,1875        2,234375
2,234375      2,21875


Сообщение отредактировал testuser2 - Четверг, 01.05.2025, 10:37
 
Ответить
СообщениеВывод значения в одну и ту же ячейку, ни какой разницы в скорости, Api vs Com
[vba]
Код
Sub TestSpeed()
    Dim lRet As Excel4ReturnCodes
    Dim xNum As XL12Num, xRef As XL12Ref
    Dim xSRef As XL12SRef, i#, t1!, t2!
    Dim d#, oCell As Range
        
    MdCallBack12 xlfIndirect, 1, TempStr12p("B8"), xSRef
    Set oCell = Range("B6")
    
    xNum.xltype = xltypeNum
    t1 = Timer
    For xNum.dVal = 1# To 30000#
        Excel12p xlSet, 0, 2, VarPtr(xSRef), VarPtr(xNum)
    Next
    t1 = Timer - t1
    
    t2 = Timer
    For d = 1# To 30000#
        oCell.value = d
    Next
    t2 = Timer - t2
    
    Debug.Print t1, t2
End Sub
[/vba]
Результат
2,1875        2,234375
2,234375      2,21875

Автор - testuser2
Дата добавления - 01.05.2025 в 10:33
testuser2 Дата: Четверг, 01.05.2025, 11:42 | Сообщение № 3
Группа: Пользователи
Ранг: Новичок
Сообщений: 12
Репутация: 4 ±
Замечаний: 0% ±

2019
Вывод 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
[/vba]
Результ
[vba]
Код
0,734375      0,6875
0,59375       0,6875
0,6132813     0,6953125
[/vba]


Сообщение отредактировал testuser2 - Четверг, 01.05.2025, 11:46
 
Ответить
СообщениеВывод 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
[/vba]
Результ
[vba]
Код
0,734375      0,6875
0,59375       0,6875
0,6132813     0,6953125
[/vba]

Автор - testuser2
Дата добавления - 01.05.2025 в 11:42
testuser2 Дата: Четверг, 01.05.2025, 17:45 | Сообщение № 4
Группа: Пользователи
Ранг: Новичок
Сообщений: 12
Репутация: 4 ±
Замечаний: 0% ±

2019
В 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
    
    bData = GetFileBytes("C:\Users\User\Documents\Excel\ExcelApi\ТекстовыйФайл.txt")
    
    'Сохранение бинарных данных
    xName = GetXl12Str("TestBDName")
    xData.xltype = xltypeBigData
    xData.BD.lpbData = VarPtr(bData(0))
    xData.BD.cbData = UBound(bData) + 1
    lRet = Excel12p(xlDefineBinaryName, 0, 2, VarPtr(xName), VarPtr(xData))
    
    Erase bData
    LSet xData = xlEmp
    
    'Получение бинарных данных
    If MdCallBack12(xlGetBinaryName, 1, VarPtr(xName), xData) = xlretSuccess Then
        ReDim bData(xData.BD.cbData - 1)
        CopyPtr lp, ByVal xData.BD.lpbData
        CopyMemory bData(0), ByVal lp, xData.BD.cbData
        MdCallBack12 xlfree, 1, VarPtr(xData)
        
        WriteBytesToFile bData, "C:\Users\User\Documents\Excel\ExcelApi\ТекстовыйФайл2.txt"
    End If
    
    'Удаление именованного выделения
    lRet = MdCallBack12(xlDefineBinaryName, 1, VarPtr(xName))
End Sub
[/vba]Все здесь


Сообщение отредактировал testuser2 - Четверг, 01.05.2025, 18:52
 
Ответить
СообщениеВ 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
    
    bData = GetFileBytes("C:\Users\User\Documents\Excel\ExcelApi\ТекстовыйФайл.txt")
    
    'Сохранение бинарных данных
    xName = GetXl12Str("TestBDName")
    xData.xltype = xltypeBigData
    xData.BD.lpbData = VarPtr(bData(0))
    xData.BD.cbData = UBound(bData) + 1
    lRet = Excel12p(xlDefineBinaryName, 0, 2, VarPtr(xName), VarPtr(xData))
    
    Erase bData
    LSet xData = xlEmp
    
    'Получение бинарных данных
    If MdCallBack12(xlGetBinaryName, 1, VarPtr(xName), xData) = xlretSuccess Then
        ReDim bData(xData.BD.cbData - 1)
        CopyPtr lp, ByVal xData.BD.lpbData
        CopyMemory bData(0), ByVal lp, xData.BD.cbData
        MdCallBack12 xlfree, 1, VarPtr(xData)
        
        WriteBytesToFile bData, "C:\Users\User\Documents\Excel\ExcelApi\ТекстовыйФайл2.txt"
    End If
    
    'Удаление именованного выделения
    lRet = MdCallBack12(xlDefineBinaryName, 1, VarPtr(xName))
End Sub
[/vba]Все здесь

Автор - testuser2
Дата добавления - 01.05.2025 в 17:45
testuser2 Дата: Пятница, 02.05.2025, 10:57 | Сообщение № 5
Группа: Пользователи
Ранг: Новичок
Сообщений: 12
Репутация: 4 ±
Замечаний: 0% ±

2019
А так можно получить уникальный идентификатор листа.
[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 - Пятница, 02.05.2025, 10:58
 
Ответить
СообщениеА так можно получить уникальный идентификатор листа.
[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
Дата добавления - 02.05.2025 в 10:57
testuser2 Дата: Понедельник, 05.05.2025, 01:58 | Сообщение № 6
Группа: Пользователи
Ранг: Новичок
Сообщений: 12
Репутация: 4 ±
Замечаний: 0% ±

2019
Copy/Cut
[vba]
Код
Private Sub Test_xlcCopy()
    Dim xRef1 As XL12SRef, xRef2 As XL12SRef, lRet As Excel4ReturnCodes
    
    MdCallBack12 xlfIndirect, 1, TempStr12p("C2"), xRef1
    MdCallBack12 xlfIndirect, 1, TempStr12p("E3"), xRef2
    
    lRet = Excel12p(xlcCopy, 0, 2, VarPtr(xRef1), VarPtr(xRef2)) 'xlcCut аналогичен
End Sub
[/vba]
Вот с xlcPasteSpecial сложнее, такая тема не работает, допустим, возвращает xlretFailed
[vba]
Код
Private Sub Test_xlcPasteSpecial()
    Dim xRef1 As XL12SRef, xRef2 As XL12SRef, lRet As Excel4ReturnCodes
    
    MdCallBack12 xlfIndirect, 1, TempStr12p("E3"), xRef1
    MdCallBack12 xlfIndirect, 1, TempStr12p("G3"), xRef2
    
    lRet = MdCallBack12(xlcCopy, 1, VarPtr(xRef1))
    lRet = Excel12p(xlcPasteSpecial, 0, 5, VarPtr(xRef2), VarPtr(GetXLInt12(xlPasteFormats)), _
                    VarPtr(GetXLInt12(xlNone)), VarPtr(GetXLBool12(False)), VarPtr(GetXLBool12(False)))
End Sub
[/vba]


Сообщение отредактировал testuser2 - Понедельник, 05.05.2025, 18:34
 
Ответить
СообщениеCopy/Cut
[vba]
Код
Private Sub Test_xlcCopy()
    Dim xRef1 As XL12SRef, xRef2 As XL12SRef, lRet As Excel4ReturnCodes
    
    MdCallBack12 xlfIndirect, 1, TempStr12p("C2"), xRef1
    MdCallBack12 xlfIndirect, 1, TempStr12p("E3"), xRef2
    
    lRet = Excel12p(xlcCopy, 0, 2, VarPtr(xRef1), VarPtr(xRef2)) 'xlcCut аналогичен
End Sub
[/vba]
Вот с xlcPasteSpecial сложнее, такая тема не работает, допустим, возвращает xlretFailed
[vba]
Код
Private Sub Test_xlcPasteSpecial()
    Dim xRef1 As XL12SRef, xRef2 As XL12SRef, lRet As Excel4ReturnCodes
    
    MdCallBack12 xlfIndirect, 1, TempStr12p("E3"), xRef1
    MdCallBack12 xlfIndirect, 1, TempStr12p("G3"), xRef2
    
    lRet = MdCallBack12(xlcCopy, 1, VarPtr(xRef1))
    lRet = Excel12p(xlcPasteSpecial, 0, 5, VarPtr(xRef2), VarPtr(GetXLInt12(xlPasteFormats)), _
                    VarPtr(GetXLInt12(xlNone)), VarPtr(GetXLBool12(False)), VarPtr(GetXLBool12(False)))
End Sub
[/vba]

Автор - testuser2
Дата добавления - 05.05.2025 в 01:58
  • Страница 1 из 1
  • 1
Поиск:

Яндекс.Метрика Яндекс цитирования
© 2010-2025 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!