2014-01-09 2 views
0

У меня есть 64-битная DLL-версия Delphi (XE4). Я называю это из Excel VBA.Excel 2013 (64 бит) VBA String + dll

Я использую следующий трюк: http://www.devx.com/tips/Tip/37587

Он работает на 32-битной и 64-битной Excel-2010, но не с первенствовать 2013

StrDataSizePtr^:=Length(tmpStr);//Access Violation here 

Что может быть проблема? Есть ли у excel-2013 vba новый формат String?

Спасибо!

EDIT:

Delphi

{$IFDEF WIN64} 
TPtrLong = UInt64; 
{$ELSE} 
TPtrLong = Longword; 
{$ENDIF} 

procedure StrToVBAStr(Str : String;VAR VBAStr : PAnsiChar); 
VAR 
    VBAStrPtr : TPtrLong absolute VBAStr; 
    ResStrSizePtr : PLongword; 
begin 
    if Length(Str)>Integer(StrLen(VBAStr)) 
    then raise Exception.Create('StrToVBAStr :  '+IntToStr(Length(Str))+'>'+IntToStr(StrLen(VBAStr))); 

    ResStrSizePtr:=Ptr(VBAStrPtr-4);//this points to VBA String size 
    VBAStr:=StrPLCopy(VBAStr,Str,Length(Str));//copy to VBAStr-be 
    ResStrSizePtr^:=Length(Str);//set VBAStr length 
end; 

function GetLastError(VAR Error : PAnsiChar) : Longint; stdcall; 
VAR 
    sError : String; 
begin 
    TRY 
    Result := _GetLastError(sError); 
    StrToVBAStr(sError, Error); 
    EXCEPT 
    Result := -1; 
    END; 
end; 

VBA

Private Declare PtrSafe Function XLDLL_GetLastErrorA Lib "XL.dll" Alias "GetLastError" (_ 
ByRef Result As String) As Long 

Public Sub XLDLL_Error(Optional ByVal Source As String = "") 
    Dim XLErr As String 

    XLErr = Space(1001) 
    If XLDLL_GetLastErrorA(XLErr) <> -1 Then 
    XL_LastError = XLErr 
    If XL_LastError <> "" Then 
     Err.Raise vbObjectError + 1000, Source, XL_LastError 
    End If 
    Else 
    Err.Raise vbObjectError + 1000, "XLDLL_Hiba", "XLDLL_GetLastErrorA hiba" 
    End If 
End Sub 
+0

Вы уверены, что "PAnsiChar", а не "PWideChar"? VBA - это язык с поддержкой Unicode –

+0

1) поскольку вы изменили исходный код, который вы указали, и из-за целей и правил StackOverflow, я прошу вас явно показать ваш фактический код в указанном выше вопросе. 2) «Нарушение доступа здесь» - показать полный и точный текст ошибки. Удаление информации об ошибках не является хорошей идеей для понимания ваших ошибок. 3) «StrDataSizePtr ^:» снова показать реальный код! 4) «Есть ли у excel-2013 vba новый формат String?» Не имеет значения, tmpStr в любом случае все равно будет изолирован от VBA, добавив код моста Delphi, если вы его не удалили –

+0

5) «функция GetLastError (ошибка VAR), откуда пришел этот VAR? Это не оригинальный пример. 6) какова ценность «StrDataSizePtr» прямо перед AV? 7) каково значение «Указатель (ошибка)»? Что такое ** ваш ** код VBA, который ВЫЗЫВАЕТ функцию? –

ответ

0

Похоже, что проблема была вызвана другой плагин Excel. На чистом новом Excel-2013 установите его отлично. После удаления плагинов из Excel-2013 ошибка исчезла.

(The VBA "строка взломать" по-прежнему работает в Excel 2013)

0

Этот код никогда не был правильным. Возможно, в прошлом это работало случайно. Возможно, внутренняя частная реализация строки VBA была изменена. Или возможно, что он остался прежним, и ваша удача только закончилась.

В любом случае правильным решением является прекращение использования частной внутренней детали реализации строки VBA. Передача строки из собственного кода в VBA достаточно просто. Нравится ли это так:

Delphi

procedure GetString(Str: PAnsiChar; var Len: Integer); stdcall; 
var 
    Value: AnsiString; 
begin 
    Value := ...; 
    StrLCopy(Str, PAnsiChar(Value), Len); 
    Len := Min(Len, Length(Value)); 
end; 

VBA

Private Declare PtrSafe Sub GetString Lib "XL.dll" (_ 
    ByVal str As String, ByRef len As Long) 
.... 
len = 1024 
buff = Space(len) 
GetString(buff, len) 
buff = Left(buff, len) 
+0

Каббл, но VBA не «управляемый код» - он основан на COM –

+0

@ChrisRolliston Я не думаю, что это действительно так или. Я бы сказал, что VBA управляется в том смысле, что он работает внутри интерпретатора VB, выполняющего p-код. Но в любом случае, у меня есть много других коннотаций, и я редактировал, чтобы изменить управляемый код на VBA. –

Смежные вопросы