Как сделать dll для excel?

Как сделать DLL для VBA?

Что нужно сделать, чтобы сделать DLL?

Я так понимаю, что нужен какой-то язык программирования.
Есть кажется VB6. Если сделать DLL, то в него можно просто поместить VBA-код, в том виде, в каком этот код находится в VBA? Или нужно изменить?

DLL хочу сделать, чтобы скрывать код макроса.

Например, такой код можно будет просто вставить в DLL или надо будет изменить:?

Как сделать надстройку в Visual Basic для VBA?
Помогите, как сделать надстройку в Visual Basic для VBA?

Как подключить dll к VBA?
пробовал так, Private Declare Function Suma Lib "D:testDLL.dll" (x As Integer, y As Integer) As.

Длинная арифметика, длинное число (LongNum) для VBA — .DLL / .XLL
Друзья, всем привет! Для всех кто любит VBA, решил написать помощник в длинной арифметики. Это.

Как подключить к VBA Excel файл DLL, лежащий в той же папке, с использованием относительного пути?
С использованием этой инструкции создал dll на С++ для подключения к VBA Excel. Подключил.

Ну да, под VBA, можно сделать любую DLL
и любой компонент с помощю среды разработки VB6
причем я уже выкладывал нативные DLL, это те которые не нуждаются в регистрации
. например здесь

Добавлено через 2 минуты
Других способов не знаю

Ну у Офиса, и VB6 общая библиотека для компиляции msvb60.dll, и много чего
общего еще, фирма одна, майкрософт называется, просто офис заточен под создание
документов, а VB6, это как-бы его родитель, и он заточен под компиляцию прочих объектов

Добавлено через 10 минут

Антихакер32, значит для меня (я только VBA знаю) подойдёт только VB6?
А когда закончится действие VB6? Есть информация?

Вообще я так представляю:

  1. сначала я делаю макрос в VBA, как обычно;
  2. затем я создаю DLL в VB6;
  3. просто копирую макросы из VBA в VB6 в DLL;
  4. сохраняю DLL;
  5. делаю в VBA «Declare» и указываю имя DLL;
  6. отдаю макрос и DLL пользователю.

Правильно я размышляю?

Да она помоему уже закончилась, поддержка VB6 насколько я знаю
тоесть майкрософт не производит обновления для него, но точной инфой не владею
помоему не так давно были внесены еще изменения, на оф-сайте должна быть инфа об этом

Добавлено через 10 минут

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

Добавлено через 4 минуты
Только надо понимать, что офис это более поздняя версия
и возможности работы с объектами на порядок больше
поэтому, для создания библиотек для офиса, нужно это учитывать
хотя все подключаемо через References и OLE-объекты

Антихакер32, с официальным сайтом VB6 не всё так просто.
Например, я делаю запрос в Гугл:
visual basic 6

На сайте написано про VB6, но если Вы дальше пойдёте, то будет написано везде «Visual Studio 8».

Поэтому всё не так просто, как Вы пишите «зайдите на официальный сайт и там посмотрите». Следы VB6 на официальном сайте невозможно найти (может быть я преувеличиваю, но впечатления такие ощущаются).

Сейчас я попробую для вас найти, ссыль

вот ссыль, а на самом сайте еще есть разветвленная структура
где можно найти все что угодно по Visual basic 6.0

The trick, а можно автоматически переводить код из VB6 в «Visual Studio Visual Basic»?
Например, я сначала делаю макрос в VBA, затем захожу в «Visual Studio», нажимаю кнопку и VBA-код переводится в VB и чтобы мне ничего делать не надо было?

А то VB6 уже совсем старый, лучше уж к новому «Visual Basic» привыкать.

Антихакер32, но могут же быть изменения в версиях. Может быть какая-то тема была год назад, но за год ведь могли произойти изменения. У меня же вопросы не по самому языку VB, а по средам. А в средах могут происходить изменения.

Как сделать dll для excel?

Полезное для программистов:

How do I make delphi functions available to Excel users?

I have seen many articles telling how to control Excel from within Delphi. However, it is also appealing to give Excel users (which tend to be far less programming oriented guys) the power of tools built with Dephi, its flexibility and velocity.

The idea is very simple and is based upon the variable types that are common to Excel’s VBA and to Delphi. Those include 32 bit integer, double precision floating point and, mainly, Excel ranges.

I found that Excel sometimes interprets incorrectly simple types when passed by reference and thus I limmited their usage to value parameters.
On the other hand, ranges can only be passed by reference and can be read from but not written to. This means that, within Delphi, you must use the reserved word CONST instead of VAR.

First, I defined within a simple unit a set of functions that convert simple Variant types to simple types and viceversa. Those are IntToVar,Double and VarTodouble (the real unit also includes a StrToVar function but not a VarToStr since this one is already included in the System unit), and are used within the procedures that do the real work (RangeToMatrix, RangeToVector,VectorToMatrix and VectortoRange).
All these functions (along with some others that you might find useful) are put together in a unit called «_Variants» whose source code is copied here (with some slight modifications).

In the real unit you will find that there fucntions that provide conversion between Excel ranges and SDL delphi component suite which I have found to be quite useful (refer to www.lohninger.com).

I shall restrict the examples, however to standard types.

Lets take first a simple function:
This function, called gamma_alfa, takes as input the mean and the variance of a population and returns the alfa parameter of a gamma distribution.

In Excel’s VBA it is declared as
Declare Function gamma_alfa Lib «c:archivosdel_filesf_auxiliares_delphi» Alias «gamma_alfa_XL» (ByVal media As Double, ByVal varianza As Double) As Double

note the lib statement that refers to name that the DLL actually has.
note also the ByVal modifiers used for declaring the variables as well as the «as double» statements.
These mean that both the input and the output will be simple types of type double.

In Delphi, the function is declared as
function gamma_alfa(media, varianza : double) : Double;stdcall;

Note the stdcall at the end of the declaration. This is to ensure that Delphi will use the Microsoft calling convention

Читать еще:  Как сделать календарное планирование в excel?

Also note the inconsistency between the delphi function’s name and the «alias» statement in VBA.
This is set in the export clause of the DLL:

Although irrelevant, the implementation of the function follows:

Now, let’s go to the tough stuff: sending Excel ranges as parameters.
Now, I will make use of a function that gets and returns excel ranges as parameters:
This function is called gamma_parametros and takes as input an histogram (with frequencies and class markers) and returns the alfa and beta parameters for a gamma. Here is its VBA declaration:

Declare Function gamma_parametros Lib «c:archivosdel_filesf_auxiliares_delphi» Alias «gamma_parametros_XL» (ByRef marcas_de_clase As Variant, ByRef frecuencias As Variant) As Variant

Now note hte «Byref» and the as «Variant» types.

In Delphi, the function is declared as follows:

and is implemented as:

Note that the functions that does the real work is not gamma_parametros_XL but gamma_parametros. The former only does the job of converting Excel ranges to TVector_ and viceversa.

the exports clause exports gamma_parametros_XL, since it’s the one that is replicated in the VBA definition, and thus it does not need a ‘name’ clause.

Here is the implementation of the gamma_parametros function:

function gamma_parametros(const marcas_de_clase, frecuencias: TVector_): TVector_;
var
pars: TVector_;
mu, sigmac: double;
begin
SetLength(pars, 2);
mu := media_ponderada(marcas_de_clase, frecuencias);
sigmac := varianza_ponderada(marcas_de_clase, frecuencias);
pars[0] := gamma_alfa(mu, sigmac);
pars[1] := gamma_beta(mu, sigmac);
gamma_parametros := pars;
end;

Here is the listing of the _Variants unit:

interface
uses SysUtils,
excel97,
vector,
matrix,
Classes,
Dialogs,
registry,
windows;

tmatriz = array of array of double;
tvector_ = array of double;

function IntToVar(dato: longint): variant;
function DoubleToVar(dato: double): variant;

function VarToDouble(const dato: variant): double;

procedure RangeToMatrix(const rango: variant; var matriz: tmatriz);
procedure RangeToVector(const rango: variant; var matriz: tvector_);
procedure MatrixToRange(const matriz: tmatriz; var rango: variant);
procedure VectorToRange(const matriz: tvector_; var rango: variant);

procedure transpose(var matriz: tmatriz);

function IntToVar(dato: longint): variant;
var
temp: variant;
begin
tvardata(temp).vtype := VarInteger;
tvardata(temp).Vinteger := dato;
IntToVar := temp;
end;

function DoubleToVar(dato: double): variant;
var
temp: variant;
begin
tvardata(temp).vtype := VarDouble;
tvardata(temp).VDouble := dato;
DoubleToVar := temp;
end;

function VarToDouble(const dato: variant): double;
var
temp: variant;
begin
try
temp := varastype(dato, vardouble);
except
on EVariantError do
begin
tvardata(temp).vtype := vardouble;
tvardata(temp).vdouble := 0.0;
end;
end;
VarToDouble := tvardata(temp).vdouble;
end;

procedure RangeToMatrix(const rango: variant; var matriz: tmatriz);
var
Rows, Columns: longint;
i, j: longint;
begin
if ((tvardata(rango).vtype and vararray) = 0) and
((tvardata(rango).vtype and vartypemask) = vardispatch) then
begin
Rows := Rango.rows.count;
Columns := Rango.columns.count;
SetLength(matriz, Rows);
for i := 0 to Rows — 1 do
SetLength(matriz[i], Columns);
for i := 0 to Rows — 1 do
for J := 0 to Columns — 1 do
matriz[i, j] := VarToDouble(Rango.cells[i + 1, j + 1]);
end
else if ((tvardata(rango).vtype and vararray) <> 0) then
begin
rows := vararrayhighbound(rango, 1) — vararraylowbound(rango, 1) + 1;
if VarArrayDimCount(rango) = 2 then
begin
columns := vararrayhighbound(rango, 2) — vararraylowbound(rango, 2) + 1;
setLength(matriz, rows);
for i := 0 to Rows — 1 do
SetLength(matriz[i], Columns);
for i := 0 to Rows — 1 do
for J := 0 to Columns — 1 do
matriz[i, j] := vartodouble(rango[i + 1, j + 1]);
end
else
begin
setlength(matriz, 1);
setlength(matriz[0], rows);
for i := 0 to rows — 1 do
matriz[0, i] := vartodouble(rango[i + 1]);
end;
end
else
begin
rows := 1;
columns := 1;
setLength(matriz, rows);
setLength(matriz[0], columns);
matriz[0, 0] := vartodouble(rango);
end
end;

procedure RangeToVector(const rango: variant; var matriz: tvector_);
var
Rows, columns: longint;
i, j: longint;
begin
if ((tvardata(rango).vtype and vararray) = 0) and
((tvardata(rango).vtype and vartypemask) = vardispatch) then
begin
Rows := Rango.count;
SetLength(matriz, Rows);
for i := 0 to Rows — 1 do
matriz[i] := VarToDouble(Rango.cells[i + 1]);
end
else if ((tvardata(rango).vtype and vararray) <> 0) then
begin
rows := vararrayhighbound(rango, 1) — vararraylowbound(rango, 1) + 1;
if VarArrayDimCount(rango) = 1 then
begin
setLength(matriz, rows);
for i := 0 to rows — 1 do
matriz[i] := vartodouble(rango[i + 1]);
end
else
begin
columns := vararrayhighbound(rango, 2) — vararraylowbound(rango, 2) + 1;
setlength(Matriz, Columns * Rows);
for i := 1 to rows do
for j := 1 to columns do
try
matriz[(i — 1) * columns + j] := VarToDouble(rango[i, j]);
except
on EVariantError do
matriz[(i — 1) * columns + j] := 0;
end;
end
end
else
begin
rows := 1;
setLength(matriz, rows);
matriz[0] := vartodouble(rango);
end;
end;

procedure MatrixToRange(const matriz: tmatriz; var rango: variant);
var
Rows, Columns: longint;
i, j: longint;
begin
Rows := high(matriz) — low(matriz) + 1;
Columns := high(matriz[0]) — low(matriz[0]) + 1;
rango := VarArrayCreate([1, Rows, 1, Columns], varDouble);
for i := 1 to Rows do
for j := 1 to Columns do
rango[i, j] := matriz[i — 1, j — 1];
end;

procedure VectorToRange(const matriz: tvector_; var rango: variant);
var
Rows: longint;
i: longint;
begin
Rows := high(matriz) — low(matriz) + 1;
rango := VarArrayCreate([1, Rows], varDouble);
for i := 1 to Rows do
rango[i] := matriz[i — 1];
end;

procedure transpose(var matriz: tmatriz);
var
Rows, Columns,
i, j: longint;
temp: double;
begin
Rows := high(matriz) — low(matriz) + 1;
Columns := high(matriz[0]) — low(matriz[0]) + 1;
for i := 0 to rows — 1 do
for j := i to columns — 1 do
begin
temp := matriz[i, j];
matriz[i, j] := matriz[j, i];
matriz[j, i] := temp;
end;
end;

One final warning note:

Notice that the types’ names in VBA are NOT the same as in Delphi.
The two must obvious are BOOLEAN (which in VBA is a 2 byte type whereas in Delphi is a one byte type). Thus you MUST use WORDBOOL in Delphi.
The other obvious type is INTEGER (in DElphi is a 4-byte type and in VBA a 2-byte type). To avoid confussion use LONGINT in Delphi and LONG in VBA

I will be more than glad to send you the full source code of the _Variant unit

VBA и DLL на D

Для правильной работы проверьте путь до M2DLL.DLL в Declare VBA Excel!

Так получилось, что пришлось мне срочно заняться одной задачей на Excel. Проблема была в том, что нужно было выбирать информацию из большого текстового файла по определенным критериям и вставлять её в Excel. Сразу пришла мысль использовать VBA и при помощи него написать функцию, которая будет выдавать мне строку с информацией.

А почему бы не написать DLL, подумал я, ведь раньше я уже пытался писать DLL для VBA на C++. DLL это быстро, это интересно и позволяет отвлечься от каждодневной рутины. Но, так как я давно уже всё делаю на D, то и DLL решил писать на D. В качестве путеводителя по дебрям VBA я использовал замечательную книгу Брюса Мак-Кинни «Крепкий орешек 4 visual basic» 1996 года выпуска. Книга исключительно интересная и занимательная и ни сколько не потеряла своей актуальности.

Читать еще:  Как сделать чтобы excel не считал скрытые ячейки?

Однако вернемся в D. Обращаю внимание, что все все примеры, которые представлены ниже, проверены только на Windows 32, Excel 2003 и dmd для Windows. Первым делом пишу строку сборки DLL, где исходный файл m2dll.d, а сама DLL будет называться m2dll.dll. Так же в сборке участвует файл dll.d входящий в поставку dmd и asc1251.d из QtE5.

dmd –ofm2dll.dll m2dll dll asc1251 -L/IMPLIB -release -shared

Небольшое введение. Существует несколько типов вызовов функций отличаются тем как передаются параметры их порядок в стеке и типами возвращаемых значений. Они все стандартизированы и в компиляторах имеются специальные дериктивы указывающие, как должен компилятор оформить функцию. Это следующие типы: pascal, stdcall, winapi и т.д. Более подробно читайте в интернете.
Итак, что у нас. У нас есть D у которого упращенно тип вызова «extern (D)». Есть Excel VBA в котором упрощенно тип вызова «extern (Windows)». DLL – это набор функций (в терминах C и C++) которые могут быть загружены во время работы приложения. Таким образом, у нас фактически будет набор функций, который мы будем вызывать из VBA. В самом VBA надо описать имя и параметры для вызываемой внешней функции.

Declare Function getAdrStringVBA Lib «r:m2dll.dll» Alias «_getAdr@4» (ByVal buf As String) As Long

Что здесь основное. Это Lib “r:m2dll.dll” – имя DLL и где она расположена, Function getAdrStringVBA – это как данная функция будет называться в VBA, Alias “_getAdr@4” – это как эта функция называется в DLL ну и напоследок список параметров и возвращаемых значений. Для D эта же функция будет выглядеть так:

export extern (Windows) int getAdr(char* buffer)

Компилятору сказано «export» — быдет видна в DLL «extern (Windows)» это тип вызова, winApi и дальше параметры. Все понятно, кроме имени внутри DLL “_getAdr@4”. Это имя экспортированной функции. Есть много литературы описывающей как задавать эти имена (например в файле DEF и т.д.) но мне лень это все описывать и намного проще в TotalCommander посмотреть список экспортированных функций по кнопке F3 на полученной DLL.

Теперь о параметрах. Дело в том, что типы параметров в VBA и D (32 разр) совпадают лишь частично!

Int D == Long VBA
Long D == нет соответствия в 32 разр VBA

Таким образом, где нам нужно в D иметь int – значит в VBA это будет long. Когда VBA в функции имеет описание о передачи строки, значит передается адрес этой строки, вернее структуры содержащей в том числе и строку.

Мне было интересно проверить расположение данных в структурах VBA, типа как их обрабатывать в D. Для этого я пользовался интерпретатором VBA (окно Immediate в VBA Excel).
Первая задача – это научится смотреть дамп памяти структуры из VBA например строки. Как получить адрес строки в VBA, если самом VBA нет понятия указатель, вернее оно присутствует неявно. Первая наша функция в DLL будет возвращать адрес строки VBA. Их описание приведено выше. В VBA возвращается число (long) которое и есть адрес. Вторая наша функция dumpForVBA(), получая long из VBA, формирует строку С формата и записывает её в буфер, который сформирован VBA внутри функции dumpPointer() :

Dim buf As String
buf = String(1000, 0)

Для испытаний, на уровне модуля VBA я определил две переменных:

Public str As String
Public adrStr As Long

Кстати, обращаю внимание, что все переменные в VBA должны быть объявлены явно, если этого не делать, то по умолчанию переменные получают тип Variant с которым D не умеет работать. Я опускаю передачу целых чисел в DLL и их возврат. Тут все просто, все передается и возвращается по значению. Это и понятно, работаем через аппаратный стек. Намного интереснее строки. Для исследования, я использую процедуру t1() в которой записан код VBA. Просмотр результата в окне Immediate. Если поставить текстовый курсор внутри процедуры t1() на любом операторе и нажать F5 – то будет выполнена эта процедура. Это избавляет от лишней писанины.

Результат выполнения:
82468836 —> 65 — 66 — 67 — 0 — 0 — 0 — 0 — 0 — 108 — 0 — 0 — 0 –
Действительно видна наша строка. Если верить «Крепкому орешку», то длина строки расположена в 32 разрядном слове левее нашей строки. Проверим. Для этого вычтем 4 (сместимся на 4 ячейки) и посмотрим дамп.
82468832 —> 3 — 0 — 0 — 0 — 65 — 66 — 67 — 0 — 0 — 0 — 0 — 0 –
Отлично видно, что длина строки равна 3.

После нескольких попыток, выяснилось, что даже в рамках одной процедуры VBA перемещает строки. Вроде по этому адресу должна быть строка, а там её уже нет! Чудеса. Для избавления от этого эффекта пришлось изменить процедуры вызова.

Пришлось ввести две лишних переменных, чтобы предотвратить выделение памяти, которое приводит к перемещению строки в памяти VBA. Теперь результат стабильный.

82338988 —> 65 — 66 — 67 — 68 — 0 — 0 — 0 — 0 — 108 — 0 — 0 — 0 —
82338984 —> 4 — 0 — 0 — 0 — 65 — 66 — 67 — 68 — 0 — 0 — 0 — 0 —

Хорошо. Но надо проверить факт, как это утверждается в документации, того, что VBA всегда ставит 0 (ноль) в конце строки. Как бы это проверить…

Интересная вскрылась ситуация. Оказывается VBA все время меняет расположение строк в памяти. Фактически каждое новое присваивание чего-то строке меняет её адрес в памяти. Причем, старая строка просто занимается новым содержимым, при том уже в формате Unicode.

Вывод:
72519660 —> 65 — 65 — 65 — 65 — 0 — 0 — 53 — 0 — 49 — 0 — 57 — 0 —
72519656 —> 4 — 0 — 0 — 0 — 65 — 65 — 65 — 65 — 0 — 0 — 53 — 0 —
72519860
72519660 —> 66 — 0 — 66 — 0 — 0 — 0 — 32 — 0 — 0 — 0 — 57 — 0 —
72519656 —> 4 — 0 — 0 — 0 — 66 — 0 — 66 — 0 — 0 — 0 — 32 — 0 —

Вначале создаётся строка из 4 букв A и это видно по адресу 72519660, потом я пытаюсь присвоить более короткую строку в надежде, что VBA экономя обращения к памяти, запишет её в тот же адрес. Однако ничего подобного не происходит. Создается совершенно новая переменная (её адрес 72519860), а в старый адрес записывается новая строка в формате Unicode.

Почитав документацию вижу следующую фразу: «VBA при обращении к внешним функциям DLL создаёт полную копию исходной строки, при этом конвертируя её из исходного формата Unicode в ASCII представление с конечным нулем для обработки функциями WinApi». Вот оно оказывается как. Теперь понятно почему оператор ms1 = «BB» вызвал создание новой копии. Это была подготовка к вызову внешней функции. Провожу ещё один эксперимент, пытаюсь понять, неужели VBA на каждое присваивание заново делает выделение памяти. Ниже кусочек кода:

Читать еще:  Как сделать порядковый номер в excel?

Вывод:
72520940 —> 66 — 66 — 0 — 0 — 65 — 0 — 65 — 0 — 65 — 0 — 65 — 0 —
72520936 —> 2 — 0 — 0 — 0 — 66 — 66 — 0 — 0 — 65 — 0 — 65 — 0 —

Вот и ответ. Забиваем строку 10 буквами A (код 65) и тут же присваиваем новое значение “BB” – которое явно короче и может использовать старый буфер. И точно – в ответе видно, что был использован предыдущий буфер, который был забит 10 буквами A в Unicod (65;0), но в него положили уже сконвертированное значение, подготовленное для передачи во внешнюю функцию.

Со строками разобрались. Вывод для работы со строками в DLL: обязательно нужна промежуточная функция на VBA, которая создаст локальный буфер большого размера, в который мы из DLL и будем записывать результирующие строки для возврата в VBA. Далее нужно извлечь из этого буфера нужное количество символов, которое мы вернем как возвращаемое значение. Пример такого подхода Public Function dumpPointer(pointer As Long, sw As Long) As String . Хорошо, а как быть со строками которые нужно отдать в DLL. А тут все просто, VBA сам выделяет буфер и ещё конвертирует из Unicode, да ещё и количество записывает, что для нас очень кстати, так как позволяет передавать и 0 в строке (фактически двоичные данные). Таким образом можно и передать и вернуть двоичные данные. Добраться до внутреннего представления строк VBA в Unicode возможно, но есть ли в этом надобность.

Рассмотрим массивы и их передачу в DLL. Начнем с массива целых чисел. Что бы получить адрес массива, мы воспользуемся той же функцией в DLL, что и для получения адреса строк. Единственно, что немного обманем VBA, написав новую декларацию.

Declare Function getAdrArrayVBA Lib «r:m2dll.dll» Alias «_getAdr@4» (ByRef buf As Long) As Long

В чем тут хитрость? В том, что мы фактически передаём ссылку на элемент массива. А как указать на весь массив, а просто передать ссылку на его первый элемент и количество таких элементов. Количество передать легко, а вот проверить возможность передачи адреса первого элемента надо.

Вывод:
72514896 —> 1 — 0 — 0 — 0 — 3 — 0 — 0 — 0 — 0 — 0 — 0 — 0 —
72514892 —> 0 — 0 — 0 — 140 — 1 — 0 — 0 — 0 — 3 — 0 — 0 — 0 —

Мы забираем адрес первого элемента массива и в дампе фактически видим сам массив в разрезе четырех байт. Отсюда вывод о том, как работать с массивами. Создаём массив большого размера, в DLL его модифицируем, передавая новую длину, и уже в VBA копируем значимую часть для сохранения результата. Аналогичный должно быть и со структурами, но проверять мне было лень…

Теперь, когда более менее ясно как обмениваться данными из VBA в DLL, вернемся непосредственно в D. Фактически разработчики уже все за нас предусмотрели написав нам dll.d!

В ней описываются точки входа и инициализация GC и Phobos. Таким образом, делать практически ничего не нужно. НО! Есть маленькое но. Так как у нас функции extern (Windows) нам не позволено пользоваться в таких процедурах всеми возможностями динамического распределения памяти. Я не могу дать четкого ответа, чем можно пользоваться а чем нет, но есть выход. Определяем обычные функции (по умолчанию они будут вызова D) и спокойно в них делаем работу, а функции extern (Windows) используем только для обмена параметрами с VBA.

Исходный код m2dll.d с комментариями, а также все необходимые файлы прикреплены ниже. А вот базу с данными, которые передавались в Excel, к сожалению, предоставить не могу, ибо в ней конфиденциальная информация.

Как сделать dll для excel?

Есть простенький код на Delphi, который компилится в DLL:

uses
ShareMem, SysUtils, Classes;

function showMeText (Str1:String): String; stdcall;
begin
Result := Str1 + » str2″;
end;

exports
showMeText index 1 name «showMeText»;

и код на VB в Excel-e:

Private Declare Function showMeText Lib «C:TempExcelDLL.dll» (ByVal S As String) As String

Dim a_text As String

При запуске скрипта Excel вылетает.

Подскажите пожалуйста, что не так?


Devel © ( 2004-12-01 16:47 ) [1]

dlea vzaimodistvia Delphi + VB lushe ispol»zovat» OleVariant


Digitman © ( 2004-12-01 16:51 ) [2]

рейсом на г.Задрипинск ?

с чего ты вообще взял, что VBA-тип STRING совместим с Паскаль-типом STRING ?


Digitman © ( 2004-12-01 16:54 ) [3]


> Devel © (01.12.04 16:47) [1]
> dlea vzaimodistvia Delphi + VB lushe ispol»zovat» OleVariant


NovaPS © ( 2004-12-01 17:01 ) [4]


> чего ты вообще взял, что VBA-тип STRING совместим с Паскаль-типом
> STRING ?

Я в этом не разбираюсь.
Мне надо чтобы DLL получила некую строку с данными, далее по ФТП загрузила данные, а потом отправила в Excel.

Подскажите как привильно написать код.


Digitman © ( 2004-12-01 17:08 ) [5]


> NovaPS © (01.12.04 17:01) [4]
> Я в этом не разбираюсь.

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

передача строковых параметров между VBA-кодом и Паскаль-кодом должна осуществлятьчся не иначе как с пом. PChar-указателей.

передача строковых параметров VBA -> Pas таким образом не вызывает никаких проблем, достаточно в VBA-коде декларировать такие параметры как ByRef .. а вот с возвратом результата Pas -> VBA дело обстоит сложнее, особенно когда длина строкового рез-та, формируемого в теле Pas-Ф-ции, заранее неизвестна.


Digitman © ( 2004-12-01 17:18 ) [6]

вот пример концептуального решения задачи:

uses
ShareMem, SysUtils, Classes;

procedure showMeText (Param:PChar; Result: PChar); stdcall;
var
tmp: String;
begin
tmp := StrPas(Param) + «BB»; //результат длиной не более 4-х символов
strcopy(Result, PChar(tmp));
end;

exports
showMeText index 1 name «showMeText»;

и код на VB в Excel-e:

Private Declare Sub showMeText Lib «C:TempExcelDLL.dll» (ByRef S As String, ByRef RsltStr As String)

Dim a_text As String
Dim Result as String

Result = » » //готовим память под результ.строку длиной 4 символа

showMeText(«AA», Result) //передаем адрес исх.строки-параметра и адрес строки, куда будет записан результат доиной не более 4 символа


NovaPS © ( 2004-12-01 17:33 ) [7]


NovaPS © ( 2004-12-01 17:49 ) [8]

Попробовал. но работать отказывается.

Ссылка на основную публикацию
Adblock
detector