Zacznę od końca.
Dlaczego nie zwalniasz zmiennej lCommand. Wydaje mi się że dlatego aby:
- Jest zmienną która ma przypisać dane do pola tablicy ( bazy danych ) za pomocą funkcji CommandText, świadczy o tym ta linia
lCommand.CommandText := Format('insert into Dane1(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);
- Po pętli for przypisuje dane za pomocą parametru do tablicy, świadczy o tym ta linia
lCommand.Execute(lCommand.Params.ArraySize);
Myślę że tak jest. Pewnie może się mylę. Ale jak wiesz biegły to ja nie jestem aż tak.
Stringgrid - Odnośnie Stringgrida już napisałem że procedurę pobrania z bazy danych za pomocą FDQuery już mam. Stringgrida ma służyć do prezentacji danych. Co do prezentacji każdy ma jakiegoś fioła. U mnie jest nim Stringgrid.
**
TStringgrid** - cały mój problem polega na tym, że nie wiem jak zapisać dane do poszczególnych kolumn w tabeli ( postgresql). Dla jasności. W zmiennej STL przechowuje dane znakowe z jakieś procedury np.
procedure Wstaw;
STL := TStringList.Create;
Wstaw(STL);
Chcę tak jak wcześniej pisałem dane z
procedure Wstaw;
przypisane do zmiennej **STL ** wstawić do tabeli o nazwie Dane1 to co podałeś w linii
lCommand.CommandText := Format('insert into Dane1(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);
po wszystkich pętlach wywołanie pod Buttonem zrobiłem tak:
procedure TForm1.Button215Click(Sender: TObject);
var
lST: TStringList;
begin
lST := TStringList.Create;
try
lST.Add('7678');
lST.Add('8546');
lST.Add('7923');
AppendDane(lST, 'D_W1;D_W2;D_W3;D_W4');
finally
lST.Free;
end;
end;
Jak słusznie zauważyłeś Twoja pierwsza procedura nie powinna być przeze mnie wpisana lecz powinienem trochę ja przerobić. Tak naprawdę to do wywołania potrzebna jest mi zmienna moja " STL" z procedury Wstaw. Wywołanie mogłoby wyglądać tak:
procedure TForm1.Button215Click(Sender: TObject);
begin
try
AppendDane(STL, 'D_W1;D_W2;D_W3;D_W4');
finally
STL.Free;
end;
end;
Dlaczego tak, ponieważ zmienna **STL ** jest już wcześniej zadeklarowana i do niej są przypisane dane a ja je tylko chcę umieścić w konkretnym polu tabeli (bazy danych postgresql).
**Dlaczego nie do pliku ** - Na moje potrzeby właśnie tym plikiem jest konkretna tabela i pole w bazie danych (Postgresql).
**Ostatnia wiadomość Twoja z kodem **- czytając zalecenia doświadczonych programistów, którzy radzą aby każda klasa była w osobnym unit-cie cały twój kod wkleiłem do osobnego unitu. Bardzo podoba mi się to rozwiązanie ponieważ jest czytelne. Ale za nic nie wiem jak wywołać w innym Unicie tą klasę, aby nie być gołosłowny pokazuję, jak to zrobiłem:
unit ULadowanie_Postgresql;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Imaging.jpeg, Vcl.ExtCtrls,
Vcl.StdCtrls, AdvPanel, Vcl.Grids, AdvObj, BaseGrid,
AdvGrid, DBAdvGrid, AdvCGrid, Vcl.Menus, AdvMenus, AdvPageControl,
Vcl.ComCtrls, Vcl.ImgList, System.Actions, Vcl.ActnList, listlink, AdvGroupBox,
AdvProgr, AdvProgressBar, AeroButtons, FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf,
FireDAC.DApt.Intf, FireDAC.Stan.Async, FireDAC.DApt, FireDAC.UI.Intf,
FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Phys, Data.DB,
FireDAC.Comp.Client, FireDAC.Comp.DataSet, FireDAC.Phys.PG,
FireDAC.VCLUI.Wait, FireDAC.Comp.UI,ShellAPI, Datasnap.DBClient;
type
TFoo = class
strict private
type
EFooException = class(Exception);
const
cErr_ParamsCount = 'Niezgodna liczba parametrów dla tokenu [%s].' + sLineBreak +
'Ilość wartości w tokenie [%d].' + sLineBreak +
'Oczekiwana ilość parametrów w bazie danych [%d].';
cErr_EmptyFields = 'Nie zdefinowano pól do których mają zostać przypisane dane.';
strict private
FConnection: TFDConnection;
strict protected
function ParseFields(const AFields: string; const APrefix : string = '') : string;
public
procedure AppendDane1(const AST: TStringList; const AFields: string);
constructor Create(AConnection : TFDConnection);
end;
implementation
uses U_Dobor_Kanalizacji_Menu_Glowne;
constructor TFoo.Create(AConnection: TFDConnection);
begin
inherited Create;
FConnection := AConnection;
end;
function TFoo.ParseFields(const AFields, APrefix: string): string;
var
lStrArray : TArray<string>;
begin
if AFields.IsEmpty then
raise EFooException.Create(cErr_EmptyFields);
lStrArray := AFields.Split([',', ';'], ExcludeEmpty);
lStrArray[0] := APrefix + lStrArray[0];
Result := Result.Join(', ' + APrefix, lStrArray)
end;
procedure TFoo.AppendDane1(const AST: TStringList; const AFields: string);
var
i : Integer;
lCommand: IFDPhysCommand;
lToken : string;
J : Integer;
begin
if Assigned(AST) and (AST.Count > 0) then
begin
FConnection.ConnectionIntf.CreateCommand(lCommand);
lCommand.Options.FormatOptions.DefaultParamDataType := ftInteger;
lCommand.CommandText := Format('insert into Dane1(%s) values(%s)', [ParseFields(AFields), ParseFields(AFields, ':')]);
lCommand.Params.ArraySize := AST.Count;
i := 0;
for lToken in AST do
begin
if lToken.Length <> lCommand.Params.Count then
raise EFooException.CreateFmt(cErr_ParamsCount, [lToken, lToken.Length, lCommand.Params.Count]);
for J := 0 to lCommand.Params.Count - 1 do
lCommand.Params[J].Values[i] := lToken.Chars[j];
Inc(i);
end;
lCommand.Execute(lCommand.Params.ArraySize);
end;
end;
end.
Gdzie:
- AppendDane1 - to procedura, która ma przypisać dane ze zmiennej STL ** (StringList) do Tabeli o nazwie Dane1 ** ( Bazy danych - postgresql).
- Dane1 - to nazwa tabeli w mojej bazie danych
- A to wszystko po to, aby dane ze zmiennej **STL ** wstawić do pól
AppendDane(STL, 'D_W1;D_W2;D_W3;D_W4');
Jak wywołać w innym unicie Twoją Klasę, tak aby dane, ze zmiennej **STL ** wstawić do tabeli **Dane1 ** ( bazy danych).
w opisie znalazłem:
nazwa_unitu.nazwa_procedury;
w moim przypadku
ULadowanie_Postgresql.AppendDane1; ale nie działa mimo że mam powiązane ze sobą unity ( alt + F11).
Na tym mój problem polega. Gdybyś teraz podpowiedział, jak mam napisać procedurę zapisująca dane ze zmiennej **STL ** to byłby wdzięczny. Myślę o rozwiązaniu 1 Klasa 1 Unit. Ponieważ jest porządek i zawsze z każdego miejsca programu można się odwołać. Jeszcze jedna uwaga. W zmiennej **STL ** może być 3 kolumny i 10000 wierszy a innym razem 5 kolumn i 1000 wierszy . chodzi o to aby wywołanie było uniwersalne tak jak to mam gdy przypisuję zmienną bezpośrednio do Stringrida. Tam sprawdzam ilość kolumn pętlą for i wiersz po wierszu zapisuję do Stringgrida. Niestety nie wiem jak zapisywać do wybranych kolumn w Stringgridzie, ale teraz mi to nie jest potrzebne. Potrzebuję zapisu zmiennej **STL ** do tabeli bazy danych i do wybranej kolumny.
Mam nadzieję że wyjaśniłem mojej problemy dokładnie.
pozdrawiam
Dłuższy