AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

AnsiStringArray aus DLL an Excel-VBA

Ein Thema von Andreas13 · begonnen am 25. Apr 2019 · letzter Beitrag vom 10. Mai 2019
 
Andreas13

Registriert seit: 14. Okt 2006
Ort: Nürnberg
711 Beiträge
 
Delphi XE5 Professional
 
#1

AnsiStringArray aus DLL an Excel-VBA

  Alt 25. Apr 2019, 22:21
Delphi-Version: XE5
Hallo Community,

ich möchte Euch erneut um Hilfe bitten! Bei folgender Aufgabenstellung komme ich leider nicht weiter:

Aus einer Delphi-DLL möchte ich einen StringVektor an Excels VBA übergeben. Dazu habe ich eine funktionierende Lösung entwickelt, die folgendermaßen aussieht:

Delphi XE5 Professional
Zielplattform: 32-Bit-DLL
Excel: 2016


Delphi-Quellcode:
library Delphi_String_for_Excel_Test;
uses
  System.ShareMem,
  System.SysUtils,
  System.Classes,
  System.AnsiStrings
;

{$R *.res}

Type
  ExcelLongInt = Int32; // {4 Bytes}


CONST
  AnsiString_Vektor_GLOBAL: Array [0..3] of AnsiString = ('1: Erster String',
                                                          '2: Das ist der ZWEITE String!',
                                                          '3: ...und hier ist der DRITTE!',
                                                          '4: Schlußlicht-String...');


                                                          
Procedure AnsiString_To_Excel(S: PAnsiChar; i: ExcelLongInt); StdCall;
// Aufgabe -> Einen Delphi-AnsiString-Vektor ZEILENWEISE an Excel-VBA übertragen

// S: PAnsiChar : zu übertragender Strings
// i: ExcelLongInt : der i-te String im globalen Vektor

VAR
  P: AnsiString;

Begin
  P:= AnsiString_Vektor_GLOBAL[i]; // Rückgabewert
  System.AnsiStrings.StrPLCopy(S, P, Length(P)); // Excels String-Array wird überschrieben
End;{AnsiString_To_Excel}
{-----------------------}

Exports
  AnsiString_To_Excel

;

begin
end.
Auf Excels Seite sieht der Code wie folgt aus:

VBA-Code:
Delphi-Quellcode:
Option Explicit

Private Declare Sub AnsiString_To_Excel Lib "Delphi_String_for_Excel_Test.dll" _
(ByVal A As String, ByVal i As Long)
' Es funktioniert!

Public Function GetDelphiStrings(Anzahl As Long)
' Zeilenweiser Aufruf der DLL-Routine AnsiString_To_Excel
' Es funktioniert!

Dim Vektor() As String
Dim NULStr As String
Dim i As Long

i = 1
'Wichtig: sonst kommen u.U. sinnlos hohe Werte beim Start und der Vektor in der DLL steigt aus: RangeCheckError!
  ReDim Vektor(1 To Anzahl, 1 To 1) ' SpaltenVektor anpassen
NULStr = String(100, vbNullChar)
'Excel MUSS den Speicherbereich zur Verfügung stellen: in der DLL wird dieser nur gepatcht!
  
  For i = 1 To Anzahl
    Vektor(i, 1) = NULStr
    AnsiString_To_Excel Vektor(i, 1), i - 1 ' !!! -1: Delphi: NULL-basiert!
Next

GetDelphiStrings = Vektor
End Function
Der Schönheitsfehler dieser Lösung besteht darin, daß ich die Strings des StringVektors ZEILENWEISE einlese, d.h. von VBA aus wird die DLL-Routine AnsiString_To_Excel n-mal aufgerufen.

Meine Idee für eine Verbesserung sieht folgendermaßen aus:

VBA-Code:
Delphi-Quellcode:
Private Declare Sub AnsiStringVektor_To_Excel Lib "Delphi_String_for_Excel_Test.dll" _
(ByVal A As String, ByVal n_Anzahl As Long)
' Es funktioniert NICHT!

Public Function GetDelphiStringVektor(Anzahl As Long)
' EINMALIGER Aufruf der DLL-Routine AnsiStringVektor_To_Excel
' Es funktioniert!

Dim Vektor() As String
Dim NULStr As String
Dim i As Long

i = 1
'Wichtig: sonst kommen u.U. sinnlos hohe Werte beim Start und der Vektor in der DLL steigt aus: RangeCheckError!
  ReDim Vektor(1 To Anzahl, 1 To 1) ' SpaltenVektor anpassen
NULStr = String(100, vbNullChar)
'Excel MUSS den Speicherbereich zur Verfügung stellen: in der DLL wird dieser nur gepatcht!
  
  For i = 1 To Anzahl
    Vektor(i, 1) = NULStr
  Next
  
  AnsiString_To_Excel Vektor(1, 1), Anzahl
  
  GetDelphiStringVektor = Vektor
End Function
Und die DLL habe ich um Folgendes erweitert:

Delphi-Quellcode:
 Procedure AnsiStringVektor_To_Excel(S: PAnsiChar; n_Anzahl: ExcelLongInt); StdCall;
// Aufgabe -> Einen Delphi-AnsiString-Vektor auf EINMAL an Excel-VBA übertragen

// S: PAnsiChar : Erstes Element des zu zu übertragenden StringVektors
// n_Anzahl: ExcelLongInt : Gesamtzahl der Strings im StringVektor


VAR
  Vektor: Array of PAnsiChar ABSOLUTE S;
  P : AnsiString;
  i : Integer;
  
Begin
  For i:= 1 To n_Anzahl Do // Excel: 1-basiertes Array
  Begin
    P:= AnsiString_Vektor_Global[i-1]; // -1: Delphi: 0-basiertes Array

    System.AnsiStrings.StrPLCopy(Vektor[i], P, Length(P)); // --> Access violation
    // System.AnsiStrings.StrCopy(PAnsiChar(Vektor[i]), PAnsiChar(P)); // --> Access violation
  End;
End;{AnsiStringVektor_To_Excel}
{-----------------------------}
...

Exports
  ...
, AnsiStringVektor_To_Excel
Leider erhalte ich aus der Procedure AnsiStringVektor_To_Excel stets "Access violation".

Im gezippten Anhang befinden sich folgende dre einsatzferige Dateien:

- Delphi_String_for_Excel_Test.dpr
- Delphi_String_for_Excel_Test.dll
- Delphi_String_for_Excel_Test.xlsm (s. Benutzungshinweise)

Was mache ich falsch? Geht es überhaupt durch nur EINEN EINZIGEN Aufruf oder nur ZEILENWEISE?

Vielen Dank für Eure Hilfe im Voraus!

Gruß

Andreas
Angehängte Dateien
Dateityp: zip Delphi_String_for_Excel_Test.zip (351,0 KB, 3x aufgerufen)
  Mit Zitat antworten Zitat
 

 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz