Урок Delphi 7
Работа с файлами в Delphi

Delphi диалоги открытия и сохранения файлов


Компоненты работающие с файлами
Классическая работа с файлами
Диалоги выбора файлов
Определение размера файла
Поиск файлов
Таблица функций






Уроки Delphi
  1.  Первая программа
  2.  Использование компонентов
  3.  События Delphi
  4.  Типы данных Delphi
  5.  Создание своих типов данных
  6.  Выражения и операторы
  7.  Работа с файлами в Delphi
  8.  Дополнительные формы
  9.  Подпрограммы в Delphi
  10. Исключительные ситуации
  11. Взаимодействие приложения с пользователем
  12. Указатели в Delphi
  13. Обзор компонентов
  14. Работа со строками
  15. Создание интерфейса
  16. Графика в Delphi
  17. Многопоточность в Delphi
  18. Динамическое создание
        компонентов
Поиск по сайту




 Это важно:
   Метод Application.ProcessMessages;

 Это полезно:
   Параметр Sender в обработчиках событий;










Бояться не надо



   То, что мы узнали в предыдущей части урока, позволяет работать с файлами по адресу, жёстко записанному в тексте программы. Мы же хотим иметь возможность открывать любые файлы и работать с файлами по нашему выбору. Естественно, Delphi предоставляет нам такую возможность. Рассмотрим компоненты, позволяющие в работающей программе осуществлять выбор файлов. Delphi диалоги выбора файла позволяют указать програме, с каким файлом мы хотим работать.

   На вкладке палитры компонентов Dialogs находятся компонент Delphi OpenDialog и компонент Delphi SaveDialog. Все Delphi диалоги, находящиеся на этой вкладке, в том числе и Delphi диалоги выбора файла, невизуальные, т.е. при переносе их на Форму в работающей программе их не видно, они видны только на этапе конструирования. Компонент Delphi OpenDialog позволяет открыть в нашей программе стандартное Windows-окно диалога открытия файла, компонент Delphi SaveDialog - окно диалога сохранения.

Delphi компоненты выбора файла

   Delphi диалоги выбора файла сами по себе ничего не делают, а только предоставляют настройки, сделанные пользователем при выборе файла. Самый важный метод Delphi диалогов - Execute. Он срабатывает в момент нажатия кнопки "открыть" или "сохранить" в окне выбора файла. Для примера давайте введём в программу возможность выбора файла для загрузки в редактор Memo, и сохранения после редактирования.

   Итак, кидаем на Форму оба Delphi диалога, текстовый редактор Memo, и три кнопки Button. В свойство Caption одной из них записываем "Открыть...", другой - "Сохранить", третьей - "Сохранить как..."

Работа с диалогами выбора файла

В обработчике OnClick кнопки "Открыть..." пишем:

   if OpenDialog1.Execute then
      Memo1.Lines.LoadFromFile(OpenDialog1.FileName);

В результате выбора файла свойство FileName компонента OpenDialog получает значение полного адреса выбранного файла, который мы и вставляем в функцию загрузки файла компонента Memo.
Всё это хорошо, но только в данном случае, когда записанное выражение записывается в одну строку. Если программа использует несколько раз выражение OpenDialog1.FileName, то писать руками устанешь. В Delphi для такого случая есть так называемый "оператор присоединения" with. Он используется для любых объектов, имеющих длинный "хвост" из свойств, которые приходится записывать многократно. Вот как он записывается:

   with Объект do
     begin

     end;

Свойства Объекта внутри логических скобок begin/end можно записывать непосредственно. Допускается перечислять через запятую несколько объектов. Естественно, в случае, когда внутри скобок находится один оператор, они необязательны. Перепишем фрагмент загрузки файла с использованием оператора присоединения:

   with OpenDialog1, Memo1 do
      if Execute then
         Lines.LoadFromFile(FileName);

Запись получается более компактной.
Так как свойства компонентов OpenDialog и SaveDialog одинаковы, сохранение текста выглядит абсолютно аналогично. Создаём обработчик нажатия кнопки "Сохранить как..." и пишем:

   with SaveDialog1, Memo1 do
      if Execute then
        begin
           Lines.SaveToFile(FileName);
           OpenDialog1.FileName:=FileName; // Чтобы исправленный текст не затёр источник
        end;

Наконец, для кнопки "Сохранить" пишем:

   Memo1.Lines.SaveToFile(OpenDialog1.FileName); // Сохраняем туда, откуда считали

(В предыдущей строчке была ошибка. Как справедливо заметил в комментариях Oraculum - OpenDialog1.FileName нужно писать без кавычек.)

   При работе этих фрагментов можно заметить, что выбирать приходится из всех файлов в нужной директории. Удобнее видеть только, например, текстовые файлы, или другой тип файлов по нашему выбору. Для этого используются фильтры, свойство Filter в наших компонентах. Настраивается оно в Инспекторе Объектов. При выборе его можно перейти в редактор фильтров:

Редактор фильтров


В колонке FilterName записываем имена фильтров, в колонке Filter - список масок файлов, разделённых точкой с запятой. Маска файла в данном случае выглядит как

    * . расширение_файла ;

Звёздочка означает, что выбираются файлы с любыми именами, подходящие по расширению.

   Свойство Delphi диалогов Title позволяет записать в заголовок нужную нам фразу. Если оставить его пустым, то в заголовке будут стандартные "открыть" или "сохранить"
   Свойство InitialDir позволяет в момент открытия оказаться в нужной нам директории. Оно доступно как на этапе "конструирования", так и программно.

   Теперь, пользуясь всем пройденным материалом, можно решить задачку на тему: как определить размер файла


Предыдущий урок           В начало урока          Следующий урок  

Уроки Delphi начинающим



Вопросы и комментарии (132)      Решение задач в Delphi

Oraculum, добавлено 23.10.09, 17:18:24 
Memo1.Lines.SaveToFile('OpenDialog1.FileName');

Одинарные кавычки не нужны, зачем вы их поставили?
Автор, добавлено 23.10.09, 17:59:50 
Справедливо! Спасибо! Но теперь не знаю, исправлять или нет, кто будет читать комментарии - не поймёт...
Александр , добавлено 29.10.09, 01:14:25 
Огромное спасибо! Полезная инфа!
evgen_aka_white, добавлено 16.12.09, 20:59:15 
Когда сохраняешь файл он не добавляет расширение txt, получается как бы просто файл. В чем проблема? Может я что-то не правильно сделал?
evgen_aka_white, добавлено 16.12.09, 21:00:15 
Уроки супер!!! Спасибо!!!
Автор, добавлено 17.12.09, 00:22:16 
Насчёт txt. Все добавляемые расширения создаются не сами по себе, а добавляются программой, если это предусмотрено программистом. Поэтому, если в программе это не запрограммировано, имя файла нужно писать с расширением. Так как пользователь заранее не знает этого, то программист обязян анализировать имя файла, и при необходимости расширение дописывать:
if pos('.', SaveDialog1.FileName)=0 then
  SaveDialog1.FileName := SaveDialog1.FileName + '.txt';
То есть если пользователь поставил точку, то расширение добавлено, если нет, то добавит программа.
Алексей, добавлено 30.03.10, 14:45:29 
В редакторе свойств (...) создание OpenDialog-a возможно?
Автор, добавлено 30.03.10, 16:06:45 
Возможно динамическое создание любых компонентов, но не в редакторе, а программно, с помощью конструкторов Create.
Шолпан, добавлено 21.07.10, 10:48:31 
Супер! Спасибо огромное, быстро и доходчиво!
Никита, добавлено 26.09.10, 21:00:19 
а почему у меня когда я сохраняю файл он пишет имя файла не то которое я ввёл а filename ?
никита, добавлено 26.09.10, 21:05:13 
о всё терь работает спасибо за статью
Иван, добавлено 28.10.10, 22:32:28 
А вот на счет сохранения, у меня к примеру два фильтра. Как сделать так, чтобы если выбрал 1 фильтр сохранил с таким-то расширением, если выбрал второй, значит с таким.
Автор, добавлено 29.10.10, 07:01:37 
Как я уже писал в тексте статьи, сами диалоги ничего вообще не открывают и не сохраняют. Вы сами должны проанализировать, какой фильтр выбран, и при сохранении подставить соответствующее расширение.
Иван, добавлено 29.10.10, 14:20:55 
Но как? Какой свойство может послужить анализации, я пробывал событие OnTypeChange, но без результатов.
Автор, добавлено 29.10.10, 14:35:15 
Достаточно просто посмотреть в Инспекторе Объектов на свойства компонента SaveDialog, чтобы обратить внимание на второе свойство со словом Filter:

FilterIndex

Ну прям не знаю, что бы это могло быть, как не номер фильтра. Если фильтр выделяет две категории, например, текст и программы, то при выделении текста FilterIndex=1, а при выделении программ - FilterIndex=2. Ну и так далее. Вот процедура:

procedure TForm1.Button1Click(Sender: TObject);
var ext: String;
begin
with SaveDialog1 do
  if Execute then
    begin
      if FilterIndex=1
        then ext:='.txt'
        else ext:='.exe';
      Memo1.Lines.SaveToFile(FileName+ext);
    end;
end;

Иван, добавлено 29.10.10, 15:23:46 
А еще. Может не сюда пишу, можно ли запретить в RichEdit'е, чтобы туда фокус не попадал, т.е. курсор редакторирования текста. Я сделал свойство ReadOnly=True. Теперь мне нужно чтобы курсор нельзя было туда поставить вообще. Такое возможно?
Иван, добавлено 29.10.10, 15:29:15 
И на счет расширения, я помню про FilterIndex, но честно скажу что не подумал что это можно сделать через переменную, я пробывал просто напрямую.
Автор, добавлено 29.10.10, 15:31:36 
Да, это просто. Есть событие OnEnter, происходящее в момент перемещения фокуса ввода в компонент, и метод компонента SetFocus. Создаём обработчик события OnEnter компонента, и там с помощью метода SetFocus перемещаем фокус на любой другой компонент:

Component.SetFocus;

Таким образом, фокус, не успев появиться в запретном месте, уйдёт из него туда, куда нам надо.
Иван, добавлено 29.10.10, 15:33:22 
И спасибо за подсказку :) На счет сохранения расширения :)
Иван, добавлено 29.10.10, 15:34:22 
А, ну я так и думал. Чтобы переместить фокус в другое место. Я думаю можно это сделать иначе :)
Иван, добавлено 29.10.10, 15:37:15 
Кстати можно даже сделать по события OnMouseMove, чтобы вообще если мышь так сказать попадает в область эдита, то сразу фокус в другой место :)
Иван, добавлено 29.10.10, 15:38:33 
Хотя нет :)
Иван, добавлено 29.10.10, 15:41:33 
Еще хотел спросить. Можно ли в компоненте PageControl, запретить переключение вкладкой с помощью мыши. Просто у меня они переключаются программно, кнопками.
Автор, добавлено 29.10.10, 17:21:17 
А кому плохо, если пользователь мышкой будет работать, как ему привычнее? Зачем надо ему это запрещать? В Windows вообще элементы управления дублируются, для удобства пользователя. Например, главное меню можно и мышкой тыкать, и с клавиатуры делать выбор того или иного пункта... Так что мой совет: не заморачивайтесь.
Дмитрий, добавлено 29.10.10, 21:55:55 
У меня почему-то кодга я сохраняю содержимое TMemo методом SaveToFile под каким бы то ни было именем, в папке создается всегда один и тот же файл с именем FileName(без расширения), в котором информация с TMemo.

Как исправить?
Автор, добавлено 30.10.10, 07:09:58 
FileName написано в кавычках? - Убрать кавычки. Расширение само не возникнет, дописать в программе. Обратите внимание на мой вчерашний ответ Ивану (29.10.10, 14:35:15)
Гость, добавлено 30.12.10, 19:54:18 
ПОдскажите пожалуйста почемуто у меня не работает кнопка Сохранить
код кнопки

procedure TForm1.Button6Click(Sender: TObject);
begin
Memo1.Lines.SaveToFile(OpenDialog1.FileName);
end;
Автор, добавлено 30.12.10, 20:43:03 
Возможно, у вас не определен адрес, т.е. OpenDialog1.FileName. Он определён, если был его вызов ранее. Проверьте.
гость , добавлено 30.12.10, 21:22:43 
вот три кнопки они должны открывать сохранять и сохранять как


procedure TForm1.Button5Click(Sender: TObject);
begin
if opendialog1.Execute then
Memo1.Lines.loadfromfile(opendialog1.filename);
end;

procedure TForm1.Button7Click(Sender: TObject);
begin
if savedialog1.Execute=true then
memo1.Lines.SaveToFile(savedialog1.FileName);
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
Memo1.Lines.SaveToFile(OpenDialog1.FileName);
end;

что нужно исправить во второй кнопке что она сохраняла
Автор, добавлено 30.12.10, 21:52:56 
Ничего, всё как надо. В чём ошибка? Файл обратно не считывается?
гость , добавлено 30.12.10, 22:07:59 
Корочи я открываю фаил дописываю его потом жму сохранить как потом снова дописываю нажимаю сохранить и фиг(((
Автор, добавлено 30.12.10, 22:21:15 
Что-то вы как-то путано написали. По моей логике, сначала вы нажимаете кнопку "Сохранить как", а потом в открывшемся диалоге сохранения дописываете имя файла, а не наоборот. Проверьте логику работы программы... Я сейчас вот что написал:

procedure TForm1.Button1Click(Sender: TObject);
begin
if SaveDialog1.Execute then
  Memo1.Lines.SaveToFile(SaveDialog1.FileName);
end;

и всё работает. С вашей процедурой разницы не вижу. Может, файл создаётся, просто вы его не замечаете? Поставьте ещё один Memo и напишите

procedure TForm1.Button7Click(Sender: TObject);
begin
if SaveDialog1.Execute then
  Memo1.Lines.SaveToFile(SaveDialog1.FileName);
  Memo2.Lines.LoadFromFile(SaveDialog1.FileName);
end;

Посмотрите, что будет в Memo2.
гость добавлено 30.12.10, 22:38:20 
все спасибо все заработало
модератор добавлено 17.01.11, 14:16:16 
достаточно информативно вы изложили компоненты-диалоги для работы с ФАЙЛАМИ.
Антон, добавлено 25.01.11, 20:34:35 
У меня он почему-то открывает файлы только формата .txt или .ini. Почему? И как заставить работать его, скажем, с таблицами excel'а?
Антон, добавлено 25.01.11, 20:36:14 
Извиняюсь, формат - только .txt, .ini он тоже не хочет открывать, в Memo1 выводит какую-то блиберду.
Автор, добавлено 25.01.11, 22:52:14 
диалог эти файлы видит? А Memo не обязательно должен отображать то, что туда напихали. Может, формат не тот, или кодировка. Попробуйте открыть файл блокнотом, посмотрите что будет.
Аноним, добавлено 26.01.11, 19:26:38 
Диалог файлы видит, но проблема в том, что он не хочет потом сохраненные Word'овские файлы нормально открывать, выдает кучу ошибок и вылетает. И все же как его заставить работать с excel'ом?
Автор, добавлено 26.01.11, 20:03:36 
Я же и говорю, попробуйте открыть екселевский файл блокнотом, и потом вопрошайте:
"А почему это у меня там абракадабра?" - А потому что это не текстовый файл!!!
И компонентом Memo, как и блокнотом, его открыть нельзя. Вернее можно, но будет именно оно.
Также и формат документов Word'а - это не текст, как вы не поймёте. А вот если вы выберете "сохранить как" в Word'е: "как текст" - другое дело.
Антон, добавлено 27.01.11, 19:30:20 
Так в том то все и дело, что я сохраняю именно как в Word'е. Но тем не менее - ошибка. А про excell я так ответа и не получил. То что это не текст, эт я уже понял, тогда как вывести данные в создаваемую мной программу?
Автор, добавлено 27.01.11, 21:37:35 
Для того, чтобы прочитать информацию из Excel'а и Word'а, нужно научиться с ними работать. Для работы с такими документами есть компоненты на страничке палитры компонентов Servers, а также другие методы. В принципе, это не очень сложно. Но, честно говоря, у меня лично пока не было планов писать про это. Может, позже. Прошу меня простить великодушно...
Антон, добавлено 29.01.11, 12:56:29 
Ну спасибо хоть на том что есть. Будем пробовать.
Ори, добавлено 13.06.11, 23:18:51 
Оно то все хорошо только что то файл сохраняется без расширения .txt, просто название файла и все, а txt потом доделывается ручками в "переименовать файл".
Ори, добавлено 13.06.11, 23:26:10 
if pos('.', SaveDialog1.FileName)=0 then
  SaveDialog1.FileName := SaveDialog1.FileName + '.txt';
а если мне надо сохранить файл как .pl то тогда как писать при этом и .txt иногда надо

Автор, добавлено 14.06.11, 05:21:03 
Ну, как надо, так и сохраняйте. Иногда приписывайте .pl, иногда .txt. Анализируйте используемую маску, или другой критерий, короче вам виднее.
Артур, добавлено 20.07.11, 13:40:24 
А как сохранить число или запись в файл с помощью диалоговых окон?
Автор, добавлено 20.07.11, 14:34:05 
В чём проблема-то? Создаёте диалоговое окно, пользователь вводит имя файла, и вы его в этот файл и сохраняете... Перечитайте всю тему про работу с файлами, не ленитесь.
Сергей, добавлено 23.07.11, 18:47:30 
У меня такая проблема.Хочу сделать так чтобы настройки программы сохранялись в файл (такой себе конфиг) в папке с программой,а при включении программы загружались. Все почти получилось, но появилась непонятная проблемка. Мне нужно чтобы путь к другому файлу (который отображается в Edit1) записывался в первую строчку файла config.ini. Если вписать путь вручную, то после нажатия кнопки сохранить - все сохранится, а если указать через opendialog.Filename, то сохранение почемуто не происходит(даже если все удалить из Edit1). Либо это какието глюки програмы либо я чет не то делаю...
Окрытие диалога спользую такое
procedure TForm2.Button1Click(Sender: TObject);
begin
if opendialog1.Execute then
Begin
Edit1.Text:=opendialog1.FileName;
end;
end;

 сохраняю так:
procedure TForm2.Button2Click(Sender: TObject);
var dir : string;
begin
getdir(0,dir);
dir:=dir+'\config.ini';
Memo1.Text:=Edit1.Text;
Memo1.Lines[0]:=Edit1.text;
Memo1.Lines.SaveToFile(dir);
end;

В чем ошибка? Компилятор ошибок и предупреждений не обнаружил.
Автор, добавлено 24.07.11, 07:03:47 
Ну вот вы не увидели файла там, где ожидаете. А проверить, куда же вы его засовываете, лень что-ли? Понятно, что если вручную прописывать пути, то найдёте там файл. А что через OpenDialog получается, ведь можно посмотреть... Ваш getdir записывает адрес текущего каталога. А текущий каталог сейчас тот, где содержится файл, который вы нашли через OpenDialog. Туда и пишется ваш конфиг. Вам просто нужно найти адрес папки с программой и записать в ваш dir:

dir:=ExtractFileDir(Application.ExeName);

Да и dir не нужен:

procedure TForm1.Button2Click(Sender: TObject);
begin
Memo1.Text:=Edit1.Text;
Memo1.Lines.SaveToFile(ExtractFileDir(Application.ExeName)+'\config.ini');
end;

Сергей, добавлено 24.07.11, 16:22:43 
Большое спасибо! Все работает =)
Иван, добавлено 4.08.11, 11:25:53 
Здраствуйте. а как открыть файл из каталога с программой, чтобы не выскакивало окно поиска файла?
Автор, добавлено 4.08.11, 14:24:31 
Файл какого типа, в чём открыть? Поясните. Например, "открыть текстовый файл в компоненте Memo". Если вы о имени файла, то можно указать просто имя, без указания диска и директорий.
А.Н.Оним, добавлено 2.10.11, 12:37:54 
Здравствуйте. Простите, если повторю вопрос, но мне нужно, чтоб при нажатии на кнопку "СОХРАНИТЬ" открывалось диалоговое окно сохранения файла .doc, лежащего в определенной директории компьютера (в котором будет установлена программа) на флешку пользователя. Я новенький в этом деле, поэтому если не составит труда, прошу помочь разобраться с кодом, или указать, где об этом говорится. Спасибо.
Автор, добавлено 2.10.11, 19:36:15 
У компонента SaveDialog есть свойство InitialDir (если я не ошибаюсь...). В него нужно вбить адрес каталога, который будет открываться при нажатии кнопки "Сохранить". А если это тот каталог, где установлена программа, то его можно так узнать:

SaveDialog1.InitialDir:=ExtractFileDir(Application.ExeName);

Всё. Как настроить фильтр на показ файлов *.doc читайте в тексте урока. Если что останется непонятным, спрашивайте дальше.
А.Н.Оним, добавлено 3.10.11, 23:52:44 
Всё получилось, но, к сожалению, не то, что мне нужно. Ситуация такая - у меня моноблок, на нем не закрывающееся окно программы. Мне нужно, чтоб клиент (образно говоря) при нажатии на кнопку "Сохранить" мог передать с моноблока на свой носитель файл .doc ("клиенту" в этот текстовый файл не нужно вносить какие-либо изменения, как это происходит в описанном вами уроке). Надеюсь объяснил достаточно понятно. Есть ли выход в данном случае?
Автор, добавлено 4.10.11, 15:18:26 
Просто нужно более точно формулировать вопрос. Если клиенту нужно, то я понимаю, вручную, и вышеприведенный фрагмент это позволяет. В противном случае это должна сделать программа, в обработчике кнопки Сохранить. Я правильно понял? Сегодня я в дороге, завтра разбёремся.
ГВОЗДЬ, добавлено 5.10.11, 21:03:24 
Как получить переменную filename(путь к файлу задаваемый диалогом)+(filename выводился на edit)СПАСИБО!
Автор, добавлено 5.10.11, 21:12:32 
with OpenDialog1 do
  if Execute then
    Edit1.Text:=FileName;

ГВОЗДЬ, добавлено 6.10.11, 08:47:01 
loc.file1:=Edi1.text;
if fileexists('const.txt') then fs.write(loc,sizeof(loc))
  else begin
  fs:=TfileStream.create('const.txt',fmcreate);
  fs.Write(loc,sizeof(loc));
  fs.free;
  end;
end;
Где я здесь ошибся?почему filename не записывается в файл?

Автор, добавлено 6.10.11, 09:07:18 
Должен признаться, что я этим методом работы с файлами не пользуюсь. Поэтому открыл книжку, почитать. Получается, что ваш параметр fmcreate создаёт файл, а если он уже существует, то открывает в режиме записи. Значит, проверять его существование не нужно. И ещё. Если файл существует, то вы его не открываете в режиме записи - вот он и не записывается, наверное. Думаю, что нужно убрать проверку на существование, и всё получится. Напишите, если что.
Вот, на пробу набросал, посмотрите, может поможет. На Форме две кнопки, Диалог Сохранить, Диалог Открыть, два компонента Label:

procedure TForm1.Button1Click(Sender: TObject); //Кнопка Сохранить
type TZ = Record
  X, Y: String;
end;
var Z: TZ;
 F: TFileStream;
begin
Z.X:='Первая координата';
Z.Y:='Вторая координата';
with SaveDialog1 do
 if Execute then
  try
    F:=TFileStream.Create(FileName, fmCreate);
    F.Write(Z, SizeOf(Z));
  finally
    F.Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);//Кнопка Прочитать
type TZ = Record
  X, Y: String;
end;
var Z: TZ;
 F: TFileStream;
begin
with OpenDialog1 do
 if Execute then
  try
    F:=TFileStream.Create(FileName, fmOpenRead);
    F.Read(Z, SizeOf(Z));
  finally
    F.Free;
  end;
Label1.Caption:=Z.X;
Label2.Caption:=Z.Y;
end;

ГВОЗДЬ, добавлено 9.10.11, 10:13:28 
ПРИВЕТ!
что за координаты X и Y, я в этом так и не разобрался, но нашел другой выход через сейф диалог.
Сейчас хотел спросить, чтобы программа принимала нажатия клавиш(KEYDOWN)поверх остальных окон, то есть даже в свернутом режиме
Автор, добавлено 9.10.11, 12:50:18 
Я сделал пробную программу, которая записывает в файл некую структуру. Вам нужно записывать другую - так записывайте её.

А что касается нажатия клавиш, то это называется перехват событий. Делается с помощью ловушек, т.н. хуков. Но это не так просто, и новичку объяснять не возьмусь. Так что смотрите сами запрос в Гугле "перехват нажатия клавиш delphi", вот например http://proging.h1.ru/articles/system/s3.htm.
егор, добавлено 19.10.11, 22:16:20 
не подскажите как проверить какой файл выбрал пользователь? т.е. сначало идет условие если файл1 то загрузить в стринггрид1 иначе в стринггрид2. спасибо
Автор, добавлено 19.10.11, 23:43:54 
После выбора свойство FileName содержит имя файла. Возможно, с полным путём. Собственно имя файла можно выделить функцией ExtractFileName(FileName). И проверяйте на равенство file1 или file2.
Андрей , добавлено 19.12.11, 02:48:23 
Помогите, обЪясните, почему вылитает ошибка при компиляции(Rroject Project1.exe raised exception class EFCreateError with 'Cannot create file''''. Системе не удается найти указанный путь'. Process stopped. Use Step or Run to continue.)
вот код, что в нем не так???
procedure TForm1.N3Click(Sender: TObject);
begin
 Memo1.Lines.SaveToFile(OpenDialog1.FileName);-курсор указывает на эту строчку.
end;
но если я меняю код на этот, то все в норме:
procedure TForm1.N3Click(Sender: TObject);
begin
with SaveDialog1, Memo1 do
  if Execute then
  begin
  Lines.SaveToFile(FileName);
В чем разница, просто я около месяца, как учу делфи, помогите пожалуйста!!!
Андрей, добавлено 19.12.11, 03:12:46 
Простите, забыл добавить,(я писал вам о вылете ошыбке) что после компиляции а редакторе кода на против строчки слева (with SaveDialog1, Memo1 do) вот код:
procedure TForm1.N3Click(Sender: TObject);
begin
 Memo1.Lines.SaveToFile(OpenDialog1.FileName);-курсор (точнее зеленая стрелка) указывает на эту строчку.
end;

procedure TForm1.N3Click(Sender: TObject);
begin
with SaveDialog1, Memo1 do -- вот на этом месте!!!!
  if Execute then
  begin
  Lines.SaveToFile(FileName);

Автор, добавлено 19.12.11, 08:08:01 
Мне всё ясно. Диалоги нельзя использовать просто так - без предварительной процедуры выбора, т.е. Execute. В первом варианте её нет, нет описания самого выбора файла. Вот свойство FileName и не определено. Вот втором варианте использование идёт через Execute, вот и всё получается правильно. А ещё, в первом варианте зачем сохраняете через OpenDialog - он же служит для чтения, а не для сохранения.

Хотя в принципе, код первого варианта вполне работоспособен. Нужно лишь, чтобы ранее - в другой процедуре - для OpenDialog был описан метод Execute и произведён выбор файла. Тогда путь в свойстве FileName будет определён.
Андрей, добавлено 19.12.11, 13:07:06 
Добрый день! Спасибо, все получилось, но возник еще вопрос, правильно ли я написал код, ошибок нет при компиляции, но вообще так можно писать, чтоб добавлялость расширение файла. Иначе файл создается без него? вот код:
procedure TForm1.N3Click(Sender: TObject);
begin
 with SaveDialog1, Memo1 do
  if Execute then
 Lines.SaveToFile(FileName+'.txt');
end;
Автор, добавлено 19.12.11, 15:55:40 
Да, так можно и нужно. Но можно и в диалоге назвать файл уже с расширением. Только пользователь так делать не станет. Но вы как программист должны проанализировать, а вдруг всё же с расширением имя? Тогда по-вашему получится, что файл с двумя расширениями пойдёт!
Андрей, добавлено 19.12.11, 16:43:46 
спасибо, вы можете на примере показать, а то я что-то не могу понять, как это сделать.
Автор, добавлено 19.12.11, 17:27:03 
С помощью оператора сравнения if, конечно.

with SaveDialog1, Memo1 do
  if Execute then
    if pos('.txt', FileName)<>0
      then Lines.SaveToFile(FileName)
      else Lines.SaveToFile(FileName+'.txt');

Андрей, добавлено 19.12.11, 17:35:35 
Спасибо вам большое, вы мне очень помогли.
Андрей, добавлено 19.12.11, 18:52:27 
При сохранении файла как ('сохранить как...'), решил добавить проверку о наличии файла с таким именем, написал общий код:
procedure TForm1.N4Click(Sender: TObject);
begin
 with SaveDialog2, Memo1 do
  if Execute then
  if pos('.txt', FileName)<>0
  then Lines.SaveToFile(FileName)
  else Lines.SaveToFile(FileName+'.txt');
  Memo1.Lines.SaveToFile(OpenDialog1.FileName);
  begin
  if FileExists('расчет.txt') then
  ShowMessage('Данный файл уже существует.')
  else
  ShowMessage('Данный файл отсутствует.');
end.
При компиляции ошибок нет, но при сохранении файла с любым именем вылетает Сообщение (Данный фал уже существует), ведь должно проверятся. Если имя есть вылетает сообщение, если файла с таким именем нет, то сохраняется с тем именем которое ввели, как я понимаю цикл должен быть, т. е. проверяется уже с другим именем. Простите, за мое занудство, но я пытаюсь научится. СПАСИБО!!!
Автор, добавлено 19.12.11, 22:59:28 
Ну может файл расчёт и правда существует - остался от предыдущих выполнений программы...
Юрик, добавлено 23.03.12, 17:54:27 
Скажите а как сделать так что бы файл сохранялся с именем дата в формате
yyyy.mm.dd-H:i:s
Автор, добавлено 23.03.12, 21:39:31 
Элементарно. Но двоеточий быть не должно - требование формата имён файлов в системе Windows. Например:

FileName:=DateTimeToStr(Now);

Получим 23.03.2012 21:35:53 - видим пробел и двоеточия. Пробел заменяем на черту (а можем и оставить, Windows не препятствует) а двоеточия на другой какой-нибудь символ. И всё - можно сохранять.
айбек, добавлено 26.03.12, 14:21:40 
как сделать чтобы программа на дельфи сохранила содержимое оле-контейнера на таблицу
Автор, добавлено 26.03.12, 14:28:20 
Вам нужно перенести данные, например, из таблицы Excel в Delphi, или наоборот? Сейчас пишу статью про это, сылка здесь: delphi-manual.ru/stringgrid.php, внизу статьи, к вечеру сегодня будет готово. Или уточните ваш вопрос.
Александр, добавлено 5.05.12, 21:21:36 
А можете разъяснить чем отличается открытие/сохранение с оператором присоединения и без него? а то так и не понял разницы.
Александр, добавлено 5.05.12, 21:41:34 
и не сильно понятно зачем "OpenDialog1.FileName:=FileName; // Чтобы исправленный текст не затёр источник"
у меня и без этого ничего не затирает
Автор, добавлено 5.05.12, 21:46:07 
Оператор присоединения всего лишь обеспечивает использование свойств без указания имени компонента. Иногда это сильно укорачивает запись кода и тем самым облегчает жизнь программиста.
Александр, добавлено 5.05.12, 22:19:28 
не понял вас, там же мы всеравно пишем компонент Memo1
Автор, добавлено 5.05.12, 22:25:07 
В этом уроке мы имеем в виду компонент OpenDialog.
Александр, добавлено 6.05.12, 08:33:20 
понятно.
а что насчет:

 "OpenDialog1.FileName:=FileName; // Чтобы исправленный текст не затёр источник"

у меня и без этого ничего вроде бы не затирает
Автор, добавлено 6.05.12, 11:35:45 
"Если пациент очень хочет жить - врач бессилен" :). Иными словами, я очень рад! Просто в вашей программе не создаются такие условия, чтобы запись шла в источник.
Александр, добавлено 6.05.12, 13:13:28 
Понятно, спасибо!
))), добавлено 20.05.12, 10:40:33 
Здравствуйте))такой вопрос: а если мне надо сохранить текст из нескольких Memo в одном файле и использовав одну кнопку и чтоб при этом информация с последнего не затирала предыдущие? пробовала просто через запятую перечислить Memo2,Memo3, но в итоге сохранился только третий

Автор, добавлено 20.05.12, 10:49:18 
Компонент - не догма, а его методы - руководство к действию!

Ясно, что нужно все три текста из Memo объединить в один компонент. Какой?

Ну, тупо, берём ещё один Memo и делаем его невидимым, суммируем поочерёдно туда информацию из всех трёх, и далее сохраняем.
Или можно запомнить, сколько было строк в одном из них, суммировать информацию туда, а после сохранения удалить лишние строки.

Есть StringList, в конце концов. Вам решать.
Аноним, добавлено 20.05.12, 10:59:06 
напишите пожалуйста как записать сумму например 2-х Memo?
Автор, добавлено 20.05.12, 11:03:49 
M1.Text+M2.Text

Попробуйте, если что не так - пишите.
Аноним, добавлено 20.05.12, 11:06:49 
записала так
procedure TForm1.BitBtn3Click(Sender: TObject);
begin
  Memo3:=Memo1.text+Memo2.text;
  with SaveDialog1, Memo3 do
  if Execute then
  begin
  Lines.SaveToFile(FileName);
  if pos('.', SaveDialog1.FileName)=0 then
  SaveDialog1.FileName := SaveDialog1.FileName + '.txt';
  OpenDialog1.FileName:=FileName; // Чтобы исправленный текст не затёр источник

  end;
выдает ошибку
[Ошибка] Unit1.pas(46): Incompatible types: 'TMemo' and 'TCaption'

Аноним, добавлено 20.05.12, 11:08:34 
я мне кажется ваще хрень какую то написала да((

Автор, добавлено 20.05.12, 11:21:15 
Ну почему же. Только почему

 Memo3:=Memo1.Text+Memo2.Text
 
а не

Memo3:=Mem2+Memo3????

(Это наводящий вопрос)

И вообще, задачу надо решать по частям. Сначала нужно убедиться, что при сложении в третьем мемо действительно текст тот который нужен. Ну, поставьте ещё кнопочку, временно, туда сложение, и посмотрите.
Аноним, добавлено 20.05.12, 11:26:35 

записала так
procedure TForm1.BitBtn3Click(Sender: TObject);
var b:string;
begin

  b:=Memo1.text+Memo2.text;
  Memo3.Lines.Add(b);
  with SaveDialog1, Memo3 do
  if Execute then
  begin
  Lines.SaveToFile(FileName);
  if pos('.', SaveDialog1.FileName)=0 then
  SaveDialog1.FileName := SaveDialog1.FileName + '.txt';
  OpenDialog1.FileName:=FileName; // Чтобы исправленный текст не затёр источник

  end;

end;
ЗАРАБОТАЛО!!!!))))а как сделать чтоб в начале файла сохраненного надпись Memo3 не вылезала?или так нельзя сделать((
 
Автор, добавлено 20.05.12, 11:38:47 
Ну вот. Теперь следующий шаг. Попробуйте

Memo3.Lines.Add(Memo1.Text);//Ну и так далее - переменная b не нужна.

Но это два оператора. А так:

Memo3.Text:=Memo1.Text+Memo2.Text;//Один

Очистка меmо - метод Memo.Clear. Сначала чистим , затем заполняем.
Аноним, добавлено 20.05.12, 11:54:29 
))))получилось)))спасибки огромное)без вас бы точно не справилась))
Юрий, добавлено 25.05.12, 19:57:28 
Классно, огромное спасибо, автору.
Аноним, добавлено 28.05.12, 20:25:07 
Здравствуйте,есть проблемка- прошу помощи. при сохранении из мемо в файл хочу чтоб по умолчанию стоял формат txt , но не выходит((( пишу if pos('.', SaveDialog1.FileName)=0 then
  SaveDialog1.FileName := SaveDialog1.FileName + '.txt'; , но несрабатывает((

Автор, добавлено 28.05.12, 20:35:54 
Я вот хочу познакомиться с девушкой. Говорю: давайте познакомимся. Но не срабатывает. Можете ответить почему?
Что вы мне ответите?
Аноним, добавлено 28.05.12, 20:41:51 
записала так
if pos('.txt', FileName)<>0
  then Lines.SaveToFile(FileName)
  else Lines.SaveToFile(FileName+'.txt');
  Memo1.Lines.SaveToFile(OpenDialog1.FileName);- но теперь он сохраняет и в формате txt и просто файл с неизв. форматом(т.е. 2 файла получается) че делать (((
 
Автор, добавлено 28.05.12, 20:54:11 
Потому что

Lines.SaveToFile - уже сохраняет. А

Memo1.Lines.SaveToFile - ещё раз сохраняет. Чем-то нужно пожертвовать. Выбор предоставляю вам.
Аноним, добавлено 29.05.12, 07:24:38 
((((((вы все про девочек шутите, а у меня проблемка(((ну ладно, придется жертвовать.....
Автор, добавлено 29.05.12, 12:04:35 
Да в чём вопрос? Написал же - уже сохраняет. Зачем ещё раз??? Ясно что последний оператор лишний.
Женя, добавлено 29.05.12, 15:48:30 
Здравствуйте.есть вопрос.предположим мне нужно записать в Edit число 1,09. именно 1,09 а не 1.09. Можно ли сделать так что если я на клаве я нажимаю точку(вместо запятой) то она не будет нажиматься(т.е. отображаться)

Женя, добавлено 29.05.12, 15:58:33 
Здравствуйте.есть вопрос.предположим мне нужно записать в Edit число 1,09. именно 1,09 а не 1.09. Можно ли сделать так что если я на клаве я нажимаю точку(вместо запятой) то она не будет нажиматься(т.е. не отображаеться),а запятая будет нажиматься.

Женя, добавлено 29.05.12, 15:58:35 
Здравствуйте.есть вопрос.предположим мне нужно записать в Edit число 1,09. именно 1,09 а не 1.09. Можно ли сделать так что если я на клаве я нажимаю точку(вместо запятой) то она не будет нажиматься(т.е. не отображаеться),а запятая будет нажиматься.

Автор, добавлено 29.05.12, 15:59:10 
Можно даже сделать так, что если вы жмёте точку, то будет отображаться всё равно запятая.

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if Key='.' then Key:=','//А если ничего не нужно то Key:=#0;
end;

Автор, добавлено 29.05.12, 16:03:52 
Но думаю, дело ваше в том, что преобразование в число StrToFloat неправильно происходит. Тогда хоть точку, хоть запятую ставьте - всё равно возможна ошибка, это зависит от настроек самой Windows. Поэтому нужно так:

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
const Deci=[',', '.'];
begin
  if (Key in Deci) then Key:=DecimalSeparator;
end;

DecimalSeparator - константа встроенная в Delphi, она всегда равна разделителю целой и дробной частей числа.
Аноним, добавлено 29.05.12, 16:16:38 
афигеть.......получилось!!!!вы гений!!!
Аноним, добавлено 13.06.12, 10:51:25 
Здрасти)))помогите плиз сделать одну вещь)я когда запускаю проект то выходит предупреждение [Предупреждение] Unit1.pas(613): Variable 's21' might not have been initialized. Оно в принципе мне не мешает, хотя я и не понимаю почему оно выходит ведь с переменной s21 вроде все в порядке. так вот мне хотелось бы чтобы это предупреждение не выходило(это ведь можно как то прописать, но я забыла что именно надо писать((((( Буду оч рада если вы поможете))
Автор, добавлено 13.06.12, 11:14:31 
Это компилятор при проверке кода обнаруживает, что в принципе возможна ситуация когда s21 не будет присвоено никакого значения. Вы-то знаете, что у вас всего например 2 варианта:

1. если x<0 то s21=1
2. если х>0 то s21=2 (например)

Нуля у вас быть не может по условиям задачи - вы это знаете. Но компилятор этого не знает, и говорит, что возможен вариант: если x=0 то значение s21 не определено.

Чтобы исключить это надоедливое предупреждение, присвойте в начале кода переменной s21 любое значение.
Аноним, добавлено 13.06.12, 11:36:51 
procedure TForm1.BitBtn11Click(Sender: TObject); //проверка Б.Б.
  var error:boolean;
  s11,s12,s21,s22:real;
  i,j:integer;
begin
error:=false;
try
a1:=StrTofloat(StringGrid1.Cells[2, 22])+StrTofloat(StringGrid1.Cells[2, 23]);//250+260
a2:=StrTofloat(StringGrid1.Cells[2, 21]);//240
a3:=StrTofloat(StringGrid1.Cells[2, 11])+StrTofloat(StringGrid1.Cells[2, 20])+StrTofloat(StringGrid1.Cells[2, 19]);//230+220+210
a4:=StrTofloat(StringGrid1.Cells[2, 9]);//190
a11:=StrTofloat(StringGrid1.Cells[3, 22])+StrTofloat(StringGrid1.Cells[3, 23]);//250+260
a22:=StrTofloat(StringGrid1.Cells[3, 21]);//240
a33:=StrTofloat(StringGrid1.Cells[3, 11])+StrTofloat(StringGrid1.Cells[3, 20])+StrTofloat(StringGrid1.Cells[3, 19]);//230+220+210
a44:=StrTofloat(StringGrid1.Cells[3, 9]);//190
.....и т.д
.....
.....
komz2:=(i32-a44)/z2;

s11:=0;
For i := 2 to 2 Do
For j := 2 to 8 Do
S11 := S11 + StrTofloat(StringGrid1.Cells[i,j]);
For i := 2 to 2 Do
For j := 12 to 24 Do
S11 := S11 + StrTofloat(StringGrid1.Cells[i,j]);

s12:=0;
For i := 3 to 3 Do
For j := 2 to 8 Do
S12 := S12 + StrTofloat(StringGrid1.Cells[i,j]);
For i := 3 to 3 Do
For j := 12 to 24 Do
S12 := S12 + StrTofloat(StringGrid1.Cells[i,j]);

s21:=0;
S21 := S21 + StrTofloat(StringGrid2.Cells[2,2]);
For i := 2 to 2 Do
For j := 4 to 6 Do
S21 := S21 + StrTofloat(StringGrid2.Cells[i,j]);
For i := 2 to 2 Do
For j := 9 to 11 Do
S21 := S21 + StrTofloat(StringGrid2.Cells[i,j]);
For i := 2 to 2 Do
For j := 14 to 19 Do
S21 := S21 + StrTofloat(StringGrid2.Cells[i,j]);
S21 := S21 - StrTofloat(StringGrid2.Cells[2,3]);

s22:=0;
S22 := S22 + StrTofloat(StringGrid2.Cells[3,2]);
For i := 3 to 3 Do
For j := 4 to 6 Do
S22 := S22 + StrTofloat(StringGrid2.Cells[i,j]);
For i := 3 to 3 Do
For j := 9 to 11 Do
S22 := S22 + StrTofloat(StringGrid2.Cells[i,j]);
For i := 3 to 3 Do
For j := 14 to 19 Do
S22 := S22 + StrTofloat(StringGrid2.Cells[i,j]);
S22 := S22 - StrTofloat(StringGrid2.Cells[3,3]);
except
error:=true;
p:=false;
end;
if error=true then showmessage('.......') else begin
if (s11=s21)and(s12=s22) then p:=true;
if p=true then ShowMessage('.......')

else ShowMessage('.........');
end;
end;
видите, я же присваиваю им значение 0.((((а ему все равно не нравится((

Аноним, добавлено 13.06.12, 11:38:24 
может все таки просто отключить.....
Автор, добавлено 13.06.12, 11:52:41 
Нужно сделать буквально то, что я написал: В НАЧАЛЕ кода присвоить значение.

У вас же оператор try, значит, до присвоения s21 нуля дело может и не дойти, исключительная ситуация раньше возникнет. А s21 используется и после блока try/except/end, значит эта переменная может быть не определена. Или лучше присвойте значение в блоке except/end.
Аноним, добавлено 13.06.12, 11:59:47 
))))все.....поняла в чем ошибка)))спасибо)
Роман, добавлено 10.07.12, 15:11:19 
Отличный сайт!!! Полезная информация!)) Спасибо))
Илья, добавлено 6.10.12, 20:01:42 
помогите пжл: как открыть папку? не файл, а именно папку и ее путь занести в edit.text
Илья, добавлено 6.10.12, 20:36:36 
читал про SelectDirectory, но нигде не могу его найти :( можете скринечег сделать где он находится в делфи?
Илья, добавлено 6.10.12, 20:47:24 
все допер что надо было FileCtrl подключить а я то его на панели искал... :facepalm:
Александр, добавлено 15.04.13, 22:43:37 
Помогите пожалуйста, нужно сделать так, чтобы расчеты из мемо при сохранении в word были в виде таблицы!
Серго, добавлено 28.09.13, 22:32:46 
тот кто все еще не может разобраться как сохранять файлы с расширением
функция "DefaultExt" в помощь

SaveDialog1.DefaultExt := 'txt'; сохранится в формате txt
Автор, добавлено 28.09.13, 22:38:18 
Спасибо за замечание! Но DefaultExt это не функция, а свойство компонентов SaveDialog и OpenDialog.
Сергей, добавлено 12.12.13, 16:10:58 
Помогите пожалуйста, у меня прописана процедура на сохранить как, как ее переделать так чтобы было просто сохранение в тот же файл. Дело в том что у меня в Listbox отображается только name,а autor,year и kol идут как доп. сведения, как сделать так чтобы сохранялось вся инфа в файл.

procedure TForm1.Save_AExecute(Sender: TObject);
var
  f:TextFile;
  i:Integer;
  People:TPeople;
begin
  SaveDialog1.FileName:='';
  if SaveDialog1.Execute then
  begin
  AssignFile (f,SaveDialog1.FileName);
  Rewrite (f);
  for i:=0 to ListBox1.Count-1 do
  begin
  People:=Listbox1.items.objects[i] as TPeople;
  Writeln (f,People.name);
  Writeln(f,People.autor);
  Writeln(f,People.year);
  Writeln(f,People.kol);
  end;
  CloseFile(f);
  end;
end;
Автор, добавлено 12.12.13, 17:30:57 
Непонятно. Вот у вас есть все данные, неважно как они сохраняются в программе. Делаем структуру типа Record:

type TSavePeople = Record
 Name, Autor, : String[50];//50 - длина в символах
 Year, Kol: Integer;
end;

var SavePeople: TSavePeople;
 FPeople: File of TSavePeople;

Ну и дальше делаем всё как в классической работе с файлами. Присваиваем данные полям нашей записи, и сохраняем одним Write.
Сергей, добавлено 12.12.13, 18:00:26 
Проблема в том что у меня сохраняется только name в файл, а autor,year,kol не хочет сохраняться.
Вот процедура на добавление в listbox

type
 TPeople = class
 public
  Name,Autor:string;
  Year,Kol:Integer;
  end;
procedure TForm1.AddClick(Sender: TObject);
var
 People:TPeople;
begin
  with Form2 do
  begin
  Name_E.Text:='';
  Autor_E.Text:='';
  Year_E.Text:='';
  Kol_E.Text:='';
  if ShowModal=mrOk then
  begin
  People:=TPeople.Create;
  People.Name:=Trim(Name_E.Text);
  People.Autor:=Trim (Autor_E.Text);
  People.Year:=StrToInt(Year_E.Text);
  People.Kol:=StrToInt(Kol_E.Text);
  ListBox1.Items.AddObject(People.Name,People);
  end;
  end;
end;


Автор, добавлено 12.12.13, 23:46:31 
Вам прям обязательно в листбокс добавить, или все же нужно сохранить данные? Вместо записи в листбокс опишите файловую переменную типа Tпёпле, и просто сохраните People через write. Но понять не могу, зачем описывать класс, потом его создавать, когда проще описать запись с теми же полями. И объект класса создавать не придется. Всё меньше телодвижений. Нет, конечно, если у вас там наследование...
Илья, добавлено 6.01.14, 17:52:42 
А можно ли выбрать просто Папку ну путь к ней
Автор, добавлено 6.01.14, 22:28:50 
Да, можно.
Евгений, добавлено 15.03.14, 20:45:33 
Здравствуйте. У меня возникла проблема в программе я хотел создать список только этот список создаётся из сохраненных файлов, а точнее подгружаются файлы после нажатия на кнопку сохранить подгружается в ListBox.
Автор, добавлено 15.03.14, 22:33:28 
А где вопрос? Вы хотели, я понял. А что не получилось?
Евгений, добавлено 16.03.14, 03:40:20 
Я пытаюсь понять как подгрузить список файлов сразу поле их создания.
Автор, добавлено 16.03.14, 05:54:25 
Опять непонятно, что вы делаете и что из этого не получается.

Запись в ListBox:

ListBox.Items.Add('FileName');
Оставить комментарий:

Имя  

Текст комментария

  





Интернет-магазин электрооборудования