Jednokrotny zapis kilku plików przy jednoczesnym dodaniu ścieżki do Listboxa

0

Cześć. Mam pytanie, bo przekombinowałem. Chce zapisać kilka plików naraz .txt, z 5 komponentów TMemo o różnej zawartości i o różnych nazwach plików z TEdit, po wskazaniu folderu w którym mają się zapisać lecz dodatkowo nowo utworzone pliki (ich ścieżki relatywne) od razu chce dodać do Listboxa. Jak to powinno poprawnie powinno wyglądać:

procedure TForm1.Button1Click(Sender: TObject);
var
  Path,SelectedDir: String;
begin
  Path := extractfilepath(paramstr(0)) + 'Pliki\';
  if SelectDirectory('Wybierz folder', Path, SelectedDir) then
  begin
  Memo1.Lines.SaveToFile(Edit1.Text + '.txt');
  Memo2.Lines.SaveToFile(Edit2.Text + '.txt');

 //ListBox1.Items.Add(ExtractRelativePath(extractfilepath(paramstr(0) + Edit1.Text)));
// Listbox1.Items.Add(ExtractRelativePath(extractfilepath(paramstr(0) + Edit2.Text)));
  end;
end;
0
var
  InitialPath, SelectedPath, FileName: String;
begin
  InitialPath := ExtractFilePath(ParamStr(0)) + '\Pliki\';
  
  if SelectDirectory('Wybierz folder', InitialPath, SelectedPath) then
  begin
    FileName := Concat(SelectedPath, '\', Edit1.Text, '.txt');
    Memo1.Lines.SaveToFile(FileName);
    ListBox1.Items.Add(FileName);
    
    {..}
  end;
end;

W miejscu {..} można wstawić operacje na pozostałych kontrolkach, jednak przydałoby się napisać osobną metodę opakowującą te operacje, aby nie duplikować prawie identycznego kodu pięć razy.

Nie powinieneś też w ten sposób określać rozszerzenia dla wyjściowych plików. Jeśli użytkownik poda w polu edycyjnym np. ciąg file.txt to Twój kod wygeneruje nazwę file.txt.txt i wyjdzie kicha. Użyj funkcji ChangeFileExt, która zadba o dwie rzeczy:

  • jeśli użytkownik poda nazwę pliku bez rozszerzenia to zostanie ono dodane,
  • jesli użytkownik poda nazwę pliku z innym rozszerzeniem to zostanie ono zamienione na to hardkodowane.
0
ListBox1.Items.Add(ExtractRelativePath(extractfilepath(paramstr(0) + Edit1.Text, tutaj brak parametru)));

Brakuje parametru, chociaż nie wiem co z tego wyjdzie moim pomysłem.

Poza tym w tej linijce niżej (to nie błąd) :

Path := extractfilepath(paramstr(0)) + 'Pliki\';

Chodzi o to że zapisuje mi pliki o poziom niżej nawet po zaznaczeniu folderu "Pliki" a nie w nim. Nie ma problemu mogę utworzyć Nowy folder 'Pliki\Nowy Folder' i mi zapisze w folderze "Pliki" ale inny użytkownik o tym nie wie i pusty "Nowy Folder" usunie?

0
Wąski napisał(a):

Brakuje parametru, chociaż nie wiem co z tego wyjdzie moim pomysłem.

Funkcja ExtractRelativePath pobiera dwa parametry – pierwszym z nich jest ścieżka bazowa, a drugim jest ta, która zostanie przerobiona na relatywną.

Ty powinieneś w pierwszym parametrze podać ścieżkę aplikacji, a w drugim ścieżkę określoną przez użytkownika.

0

Dzięki Wielkie za pomoc i super wyjaśnienia, Opakować w metodę już sobie poradzę , jak byś miał jeszcze chwilkę pomóc by do Listboxa dodawać ścieżkę relatywną chodzi mi by w Listboxie było \Pliki.Nazwa_pliku.txt a nie ```
C:............

```delphi
Listbox1.Items.Add(ExtractRelativePath(extractfilepath(paramstr(0) 
0

Zobacz sobie do dokumentacji – jest tam przykład użycia tej funkcji i rezultaty są inne.

Sprawdziłem też jak to wygląda w Lazarusie. Funkcja ta działa tak samo jak w Delphi. Poniżej podaję Ci przykład wywołania tej funkcji – może w ten sposób zrozumiesz jak działa:

// Result: Pliki\
ExtractRelativePath('C:\Program Files\App\', 'C:\Program Files\App\Pliki\');

// Result: ..\
ExtractRelativePath('C:\Program Files\App\Pliki\', 'C:\Program Files\App\');

I dwa przykłady ze ścieżkami plików (nie katalogów):

// Result: Pliki\plik.txt
ExtractRelativePath('C:\Program Files\App\', 'C:\Program Files\App\Pliki\plik.txt');

// Result: Pliki\plik.txt
ExtractRelativePath('C:\Program Files\App\program.exe', 'C:\Program Files\App\Pliki\plik.txt');

Idąc tym tropem i patrząc na mój poprzedni przykład, kod powinien wyglądać tak:

var
  InitialPath, SelectedPath, FileName: String;
begin
  InitialPath := ExtractFilePath(ParamStr(0)) + '\Pliki\';
 
  if SelectDirectory('Wybierz folder', InitialPath, SelectedPath) then
  begin
    FileName := ExtractRelativePath(ParamStr(0), Concat(SelectedPath, '\', Edit1.Text, '.txt'));
    Memo1.Lines.SaveToFile(FileName);
    ListBox1.Items.Add(FileName);
 
    {..}
  end;
end;
0

Dzięki Jeszcze raz.
Mi wyszło troszkę inaczej ale też działa :)


var
  InitialPath, SelectedPath, FileName: String;
begin
  InitialPath := ExtractFilePath(ParamStr(0)) + 'Pliki\';

  if SelectDirectory('Wybierz folder', InitialPath, SelectedPath) then
  begin

    FileName := Concat(SelectedPath, '\', Edit1.Text, '.txt');
    Memo1.Lines.SaveToFile(FileName);
    ListBox1.Items.Add(ExtractRelativePath(InitialPath, FileName));

// Ale tak też jest dobrze
//  ListBox1.Items.Add(ExtractRelativePath(SelectedPath, FileName));
  end;

Chyba to wszystko na jedno wychodzi, zresztą ja już trochę z głupiałem :)

0

Twój kod od mojego różni się tym, że do zapisu zawartości Memo do pliku używa ścieżki bezwzględnej, a do ListBox dodawana jest relatywna, obliczana w locie i przekazywana w parametrze. Ja najpierw wyznaczyłem ścieżkę relatywną i wrzuciłem ją do pomocniczej zmiennej, aby użyć jej do obu tych operacji.

To na jedno wychodzi, bo obie wersje ścieżek (relatywna i absolutna) wskazują na tę samą lokalizację.

Edit: Tyle że Ty użyłeś ścieżki katalogu Pliki jako bazowej, według której zostanie wyznaczona ścieżka relatywna, a nie katalogu z plikiem wykonywalnym aplikacji. Dlatego też, jeśli użytkownik wybierze katalog Pliki w oknie SelectDirectory to relatywną ścieżką pliku będzie ciąg file.txt, a nie Pliki\file.txt.

0

Jeszcze Dziękuje za cenne rady. Jeśli mógłbyś tylko spojrzeć na ogólną metodę. Na dzień dzisiejszy tylko tak to potrafiłem zrobić.

public
    SelectedPath :string;
    procedure SaveAndLoadTxt(aEdit: TEdit; aMemo: TMemo);
  end;

{...}

procedure TForm1.SaveAndLoadTxt(aEdit: TEdit; aMemo: TMemo);
var
  FileName: String;
begin
  FileName := ExtractRelativePath(ParamStr(0), Concat(SelectedPath, '\',
    aEdit.Text, '.txt'));
  aMemo.Lines.SaveToFile(FileName);
  ListBox1.Items.Add(FileName);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  InitialPath: String;
begin
  InitialPath := ExtractFilePath(ParamStr(0)) + 'Pliki\';
  if SelectDirectory('Select a folder', InitialPath, SelectedPath) then
  begin
    SaveAndLoadTxt(Edit1, Memo1);
    SaveAndLoadTxt(Edit2, Memo2);
    SaveAndLoadTxt(Edit3, Memo3);
  end;
end;
0

SaveAndLoadTxt to dość dziwna nazwa – metoda służy do zapisu zawartości Memo do plików i tylko do tego, żadnego ładowania nie wykonuje. Zwróć też uwagę na to, że ścieżka docelowa jest taka sama dla wszystkich plików, więc można ją obliczyć raz.

Luźna propozycja niżej – wyszła dość krótka:

procedure TForm1.Button1Click(Sender: TObject);
var
  AppPath, InitialPath, SelectedPath: String;
begin
  AppPath := ExtractFilePath(Application.ExeName);
  InitialPath := AppPath + 'Pliki\';
  
  if SelectDirectory('Select a folder', InitialPath, SelectedPath) then
  begin
    SelectedPath := ExtractRelativePath(AppPath, SelectedPath);
    
    Memo1.Lines.SaveToFile(SelectedPath + Edit1.Text);
    Memo2.Lines.SaveToFile(SelectedPath + Edit2.Text);
    Memo3.Lines.SaveToFile(SelectedPath + Edit3.Text);
    
    ListBox1.Items.Add(SelectedPath + Edit1.Text);
    ListBox1.Items.Add(SelectedPath + Edit2.Text);
    ListBox1.Items.Add(SelectedPath + Edit3.Text);
  end;
end;

To dodawanie pozycji do ListBox1 można by spróbować jakoś skrócić.

0

Z tą nazwą to tak na szybko bez głębszego zastanowienia :) A Twój kod jak zwykle lepszy :) Co do skrócenia dodania do Listboxa to nie jest konieczność ale ciekawa rozkminka jak dla mnie ale jak bym tego nie chciał ugryźć przybywa mi zmiennych, dodanie skróci ale kod wydłuży :) No nic, Dziękuję jeszcze raz za pomoc i super porady. Pozdrawiam

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