Wykorzystanie API ERP XL w Delphi

0

Witam
Poszukuje osoby która pomoże mi w uruchomieniu API ERP w Delphi. Konkretnie potrzebuje dodać nowy kod do Bazy XL'a z wykorzystaniem API. Nie umie sobie poradzić (jest opis na http://cdn.3lance.pl/viewtopic.php?f=13&t=378 niestety archaik link nie działa więc nie podglądne jak wywołać polecenia dodania kodu a ja ogólnie w korzystaniu z API leże). Może ktoś borykał się z tym tematem - nie proszę o dokumentację ERP API - interesuje mnie źródło i wywołanie polecenia


API2015, DELPHI 10 Seattle

0

Może zaczne trochę inaczej mam coś takiego:

   
unit Unit1;

interface

uses
....

 type XLLoginInfo = record
    Wersja          :longint;
    UtworzWlasnaSesje   :longint;
    Winieta         :longint;
    TrybWsadowy       :longint;
    ProgramID       :array[1..41] of char;
    Baza       :array[1..21] of char;
    OpeIdent       :array[1..9] of char;
    OpeHaslo       :array[1..9] of char;
    PlikLog        : array[1..200] of char;
    SerwerKlucza       : array[1..101] of char;
    end;

    type PInteger                       = ^integer;
    type PXLLoginInfo                   = ^XLLoginInfo;

type
  TForm1 = class(TForm)
    xml: TXMLDocument;
   ....
  private

    { Private declarations }
  public

  end;

var
  Form1: TForm1;
 ....

implementation

{$R *.dfm}
  function XLLogin(LoginInfo:PXLLoginInfo;Sesja:pInteger):integer;stdcall;external 'cdn_api.dll';
    function XLLogout(Sesja:integer):integer;stdcall;external 'cdn_api.dll';
    function XLSprawdzWersje(NumWersji:PInteger):integer;stdcall;external 'cdn_api.dll';

i jeszcze zmienne ale to juz daje pod button:

      
 Var
       Sesja                       : integer;
       idd:integer;
       IDDokumentu                 : integer;
       IDKontrahenta               : integer;
       Login                       : XLLoginInfo;
       DokumentNagInfo             : XLDokumentNagInfo;
       ZamkniecieDokumentuInfo     : XLZamkniecieDokumentuInfo;

i teraz nie wiem co dalej

autor pisze:

Reszta to juz kod klikniecia guzika
-sprawdzenie wersji, zalogowanie, dodanie dokumentu,zamkniecie dokumentu

jak to obsłużyć pomoże mi ktoś z tym API? Aktualizacje: cen, ean i nazwy towaru obsługuje SQL'em a towar chce dodawać po tym nieszczęsnym API może jest to banalne ale delphi uczyłem się sam i czegoś mi brakuje

2

Z czym masz problem? Nie znam tego API zupełnie i nie mogę poświęcić czasu na jego zgłębianie podobnie pewnie jak reszta forumowiczów.
Konkretny problem - konkretna odpowiedź, na razie wygląda to jak prośba o odwalenie całej roboty za ciebie.
Zapewne żeby zalogować się musisz stworzyć zmienną typu XLLoginInfo, wypełnić go danymi i podać wskaźnik na ten rekord do funkcji XLLogin w rezultacie powinieneś otrzymać kod odpowiedzi, podobnie z pozostałymi funkcjami.

0

Czyli rozumie przez to tworze zmienną:

  Login: XLLoginInfo; 

jako że zadeklarowałem ją tak:

 type XLLoginInfo = record
    Wersja          :longint;
    UtworzWlasnaSesje   :longint;
    Winieta         :longint;
    TrybWsadowy       :longint;
    ProgramID       :array[1..41] of char;
    Baza       :array[1..21] of char;
    OpeIdent       :array[1..9] of char;
    OpeHaslo       :array[1..9] of char;
    PlikLog        : array[1..200] of char;
    SerwerKlucza       : array[1..101] of char; 

to i musze wypełnić robie to tak :

 
 with Login do
  begin
  Wersja := APIWersja;
  UtworzWlasnaSesje  := 1;
  Winieta  := 1;
  TrybWsadowy  := 1;
  ProgramID  := 'testowany';
  Baza      := 'test';
  OpeIdent   := 'ADMIN';
  OpeHaslo   :='test';
  PlikLog:= 'c:\x';
  SerwerKlucza:= 'XXXXXX;
  end;

a co mam rozumieć poprzez "... i podać wskaźnik na ten rekord do funkcji XLLogin"

podstawiając wywołując funkcje

  XLLogin(login);

wywala mi
[dcc32 Error] Unit1.pas(966): E2010 Incompatible types: 'PXLLoginInfo' and 'XLLoginInfo'

Odwalenie roboty za mnie nie wchodzi w grę ponieważ nadal nie bede tego umiał a jest to tylko podstawa której jak nie pojmie nadal będe tkwił w miejscu.

2

spróbuj XLLogin(@login);

0

czyli rozumie że jak były wskażniki:

   
type PInteger  = ^integer;
type PXLLoginInfo  = ^XLLoginInfo; 

to musze wywoływać z @ w moim konkretnym przypadku:

 function XLLogin(LoginInfo:PXLLoginInfo;Sesja:pInteger):integer;stdcall;external 'cdn_api.dll';

dla Sesja

var 
sesja:integer;

musze wywołać:

XLLogin(@login,@sesja);

jezeli tak to dziękuje za pomoc na tym etapie.

Mój program "coś" próbuje robić ale teraz metodą prób i błędów musze ustalić czego mi jeszcze brakuje;

0

@omenserv - no skoro parametry są typów wskaźnikowych to chyba oczywiste, że musisz przekazać wskaźnik; Albo zadeklaruj sobie normalną zmienną rekordową (typu XLLoginInfo) i uzywając @ lub funkcji Addr przekaż wskaźnik, albo zadeklaruj sobie od razu wskaźnik na rekord typu PXLLoginInfo, następnie zaalokuj pamięć (New), uzupełnij i przekaż wskaźnik bezpośrednio, na końcu zwolnij pamięć;

Rozwiązania masz co najmniej dwa, więc zdecyduj się i w końcu spróbuj coś użyć, zamiast w kółko dopytywać; Raczej nikt nie używa tego API (bo inaczej było by więcej konkretnych postów), więc jedyne co można zasugerować to prawidłową konstrukcję - reszta należy do Ciebie.

0

Jakbym nie pytał o te szczegóły to nadal bym nie wiedział zatem bardzo Ci dziękuje szopenfx to jest to czego mi brakowało. Po ilości Twoich postów furious programming rozumie że jesteś lvl master no niestety ja do wczoraj nawet nie wiedziałem jak ugryźć użucie api. Temat od strony użycia zaczynam ogarniać jeszcze troche łykne wiedzy na temat tych wskaźników i będzie ok (już dzięki szopenfx pare innych procedur dzisiaj udało mi sie uruchomić). Jeżeli pozwolicie to zadam jeszcze pytanie otóż deklaruje sobie zmienną:

 type XLLoginInfo = record
    ...
    OpeIdent       :array[0..8] of ansichar;
  ...
    end;

i podczas jej wypełniania chciałbym wrzucic do OpeIdent np pole z edit1.text bądź cokolwiek jak to uczynić:
za każdym razem wywala mi podobne błedy dla samego char czy string np.
[dcc32 Error] Unit1.pas(999): E2010 Incompatible types: 'array[0..8] of AnsiChar' and 'TCaption'

Rozumie że poprzez deklaracje array[0..8] razerwuje mi miejsce dla tych zanaków zatem jak teraz moge "przerobić" np stringa aby go tam wepchać?

0

@omenserv - ilość postów nic nie oznacza;

Tu nie chodzi o o to jakiego API używasz - w tym przypadku nie ma to najmniejszego znaczenia; Problem polega na tym, że masz braki w podstawach programowania; Skoro argument jest wskaźnikiem to siłą rzeczy musisz w nim przekazać wskaźnik - a Ty tego nie robiłeś; I nawet nie pomógł fakt, iż autor tego API ładnie stosował się do przyjętej konwencji nazewnictwa i użył prefiksu P dla typu wskaźnikowego; Zresztą masz wgląd w deklarację tych typów;

Dokładnie ten sam problem miał @xiviali w tym wątku: **http://4programmers.net/Forum/Delphi_Pascal/264749-wczytanie_obrazka_w_allegro**; Zamiast podać wskaźnik na paletę, przekazywał całą paletę; Ja kompletnie nie znam biblioteki allegro, jednak przyczyna problemów była oczywista - brak praktycznych umiejętności z zakresu używania wskaźników;

Zrozum, że nikt nie chce Ci tutaj robić na złość (ja też tego nie chcę), jednak jeśli zabierasz się za jakikolwiek trudniejszy projekt to przydałoby się mieć jakieś zaplecze, przynajmniej solidnie przyswojone pełne podstawy programowania;


Co to nowego problemu (także podstawy), spróbuj użyć deklaracji tych pól z pierwszego Twojego posta; Albo użyj poniższej:

OpeIdent: String[9];

albo indeksuj znaki od 1, tak jak ma to miejsce w łańcuchach znaków:

OpeIdent: array [1 .. 9] of Char;

Sam użyłbym ograniczonego łańcucha zamiast macierzy.

0

Nie uważam że ktoś mi chce zrobić na złość a wręcz jestem wdzięczny za jakąkolwiek pomoc nigdy nikt mnie delphi nie uczył a wyuczyło mnie tylko google i 4programmers wraz z gotowcami które rozkładałem i patrzyłem co do czego. Do tej pory jakaś tam wiedza mi wystarczała wraz z czystym sqlem i było ok dopóki nie pojawiło sie to api i te wskaźniki jeżeli możesz to powiedz mi co byś mi proponował brak w celu "praktycznych umiejętności z zakresu używania wskaźników" tylko coś dla amatora bede wdzięczny.
p.s widzisz sam może to podstawa z tym array[0..8] of ansichar - niestety szukam już cały dzień ale wierze że znajde...

0

jeżeli zamieniam na:

  ProgramID       : array[1..41] of ansichar;
    Baza       :array[1..21] of ansichar;
    OpeIdent       :array[1..9] of ansichar;
    OpeHaslo       :array[1..9] of ansichar;
    PlikLog        : array[1..200] of ansichar;
    SerwerKlucza       : array[1..101] of ansichar;

nie kompliuje się:

 [dcc32 Error] Unit1.pas(998): E2010 Incompatible types: 'array[1..41] of AnsiChar' and 'string'
[dcc32 Error] Unit1.pas(999): E2010 Incompatible types: 'array[1..21] of AnsiChar' and 'string'
itd...

jeżeli przypisuje

OpeIdent: String[9];
itd...

zamieniam na stringi kompliuje się ale logowanie nie działa nie rozpoznaje loginu takie samo było zachowanie jak przy zmianie paru z char na ansichar. Jak indeksuje od 0.. przy ansichar wszystko działa z tym że wartości musze pisać na szytwno nie moge przekazać zmienną.

Próbowałem stworzyć coś takiego:

test:string;
i: integer;
  ProgramID_1: array[0..40] of Char;

begin
test:='program_test';
 
for I := 0 to Length(test) do
  begin
    ProgramID_1[i] := test[i];
  end;

 with Login do
  begin
  Wersja := APIWersja;
  UtworzWlasnaSesje  := 1;
  Winieta  := -1;
  TrybWsadowy  := 1;
  TrybNaprawy:=1;
  ProgramID :=  ProgramID_1;
.................

ale otrzymuje
[dcc32 Error] Unit1.pas(1008): E2010 Incompatible types: 'array[0..40] of AnsiChar' and 'array[0..40] of Char'

1

Hmm, dziwne - testuję poniższy kod pod Lazarusem w trybach OBJFPC i DELPHI i wszystko gra:

var
  arrValue: array [0 .. 8] of AnsiChar;
  strValue: AnsiString;
begin
  strValue := 'foo';
  arrValue := strValue;

  Write('Value: "', arrValue, '"');
end.

Żadnych błędów ani wyjątków - program kompiluje się i działa bezbłędnie; Widocznie Delphi zupełnie inaczej traktuje ciągi i tablice znaków, dlatego takie rzeczy wychodzą;

Jak indeksuje od 0.. przy ansichar wszystko działa z tym że wartości musze pisać na szytwno nie moge przekazać zmienną.

Tzn. możesz, wszystko możesz, ale nie za pomocą standardowego przypisania; Jeśli pola struktury koniecznie musza być macierzami znaków indeksowanymi od 0 i kompletnie nie masz pojęcia jak przepisać łańcuch ze zmiennej do takiej tablicy to pozostaje użycie FillChar w celu wyzerowania macierzy oraz Move, która skopiuje blok pamięci:

FillChar(arrValue[0], Length(arrValue), 0);
Move(strValue[1], arrValue[0], Length(strValue));

Zarówno łańcuchy znaków jak i macierze w pamięci zajmują ciągłe bloki, więc ich kopiowanie na pewno nie będzie sprawiać żadnych problemów;

PS: Nie używaj typów znakowych i łańcuchowych byle jak, bo one wszystkie nie oznaczają tego samego; Pomiędzy typami Char, AnsiChar i WideChar jest spora różnica, więc należy wybrać jeden typ dla znaków i łańcuchów i stosować je wszędzie; Jednak aby wybrać odpowiedni typ danych, należy zapoznać się z API i jego dokumentacją.

0
furious programming napisał(a):

Żadnych błędów ani wyjątków - program kompiluje się i działa bezbłędnie; Widocznie Delphi zupełnie inaczej traktuje ciągi i tablice znaków, dlatego takie rzeczy wychodzą;

no u mnie sypie jednak błedem:
[dcc32 Error] Unit1.pas(992): E2010 Incompatible types: 'array[0..8] of AnsiChar' and 'AnsiString'

będe próbował aż do bólu w specyfikacji api jest taka zmienna AS CString(41) domyślam się że autor artukułu na którym bazuje korzystał z Delphi 7 a tam z tego co pamiętam i gdzieś się doczytałem to nie było widechar i ansichar (moge byc w błedzie). Jak podstawiłem zamiast char ansichar to śmiga teraz próbuje rozkminić i pokombinuje z ansistring.

0

będe próbował aż do bólu w specyfikacji api jest taka zmienna AS CString(41) domyślam się że autor artukułu na którym bazuje korzystał z Delphi 7 a tam z tego co pamiętam i gdzieś się doczytałem to nie było widechar i ansichar (moge byc w błedzie).

W starych Delphi były typy AnsiChar i WideChar;

domyślam się że autor artukułu na którym bazuje korzystał z Delphi 7

To jest napisane na początku posta - http://cdn.3lance.pl/viewtopic.php?f=13&t=378#p2146; Natomiast to co napisałeś:

w specyfikacji api jest taka zmienna AS CString(41)

oznacza, że API nie jest napisane w Delphi, a w C;

Trzeba by poczytać w dokumentacji języka o tym CString oraz znaleźć w dokumentacji API wzmiankę o kodowaniu, jakie jest w nim używane; Bez tego można jedynie uprawiać programowanie randomowe i nawet jeśli coś zacznie działać prawidłowo to nie będzie pewności, że będzie działać zawsze.

0

masz racje:

...Prototypy funkcji i struktury danych wykorzystywane przez funkcje API zawarte w niniejszym dokumencie zostały podane w dialekcie Visual Basic’a....

...Funkcje Windows API były tworzone z myślą o programistach piszących w C/C++ i podczas deklaracji funkcji w nazwie czasami pojawiają się znaki niedozwolone w VB (np. znak podkreślenia "_")...

1

A co z kodowaniem łańcuchów?

0

jakie to było proste dzieki furious programming od 2h podstawiam przed wywołaniem... no ale to podstawy :D działa jak należy podmienia co chce i bez wykrzaczania oczywiście pozostałem a ansichar. Jeszcze raz dziękuje

0

Mam jeszcze takie inne dziwne zachowanie:

otóż tworze zmienną

 kod_towaru_api:ansistring;

i w pętli for.. przypisuje zmienne

  

with CenaInfo do
  begin
  Wersja := APIWersja;
  Numer:= 1;
  Kod :='kod_testowy';
  Waluta:='PLN';
  Wartosc:='0,01';

  end;

//// kod towaru
FillChar(CenaInfo.Kod, Length(CenaInfo.Kod), 0);
Move(kod_towaru_api[1], CenaInfo.kod[0], Length(kod_towaru_api));

 //// cena
FillChar(CenaInfo.Wartosc, Length(CenaInfo.Wartosc), 0);
Move(cena_towary_api[1], CenaInfo.Wartosc[0], Length(cena_towary_api));

XLZmienCene(@CenaInfo);
 showmessage('>'+CenaInfo.kod+'<cena:'+CenaInfo.Wartosc);

i wszystko było by ok (robie podgląd wywołaniu sohwmessage) -CenaInfo.kod jest ok jak i CenaInfo.Wartosc to jednakże w bazie po wywołaniu

XLZmienCene(@CenaInfo);

CenaInfo.kod -zapamiętuje ten pierwszy i tylko dla niego przypisuje cene z pętli CenaInfo.Wartosc. Jest jakaś opcja czyszczenia = zerowania?

Po przeprowadzeniu "paru" testów i przeczytaniu "paru" ciekawostek. Okazuje się ze ta funkcja ma pare zmiennych powiązanych m.in GIDNumer który jeżeli występuje ignowowany jest Kod. Dlatego też przy pierwszym wywołanie funkcji przekazujemy do bazy nasz KOD a chcąc nie chcąc podczas aktualizacji "przykleja się nam GIDnumer stąd też moje pytanie ponieważ jest to zmienna typu integer w jaki sposób mogę ją "wyzerować" w taki sposób aby nie miała żadnej wartości GIDNumer:=null powoduje bład jak moge się pozbyć z niej wartości niechcianej.

0

Jakby ktoś miał kiedyś podobny problem to sam sobie odpowiem:

ZeroMemory(@CenaInfo, SizeOf(CenaInfo)); 

rozwiązało problem :D
Temat uważam za zakończony prosze o zamkniecie.
Dziękuje furious programming za podstawy

1 użytkowników online, w tym zalogowanych: 0, gości: 1