powered by simpleCommunicator - 2.0.29     © 2024 Programmizd 02
Map
Форумы / Языки программирования семейства Pascal [закрыт для гостей] / Заметки о Делфи.
Модераторы: s62
27 сообщений из 27, показаны все 2 страниц
Заметки о Делфи.
    #708667
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
У меня сейчас на работе основной ЯП - Delphi. Хотя относительно давно на нем программирую, все равно какие-то новые штуки узнавал в последнее время. Буду тут писать.

Первое. Есть в Delphi, как и в других языках, функция Format. Но есть и частные функции для форматирования вывода разных данных. Например для вывода чисел с плавающей запятой - FormatFloat.
Я думал, что эта функция, когда задаешь кол-во знаков после запятой, просто обрезает остальные десятичные знаки. Сегодня узнал, что она всё-таки округляет до заданного кол-ва знаков. И это хорошо,что округляет. )
...
Рейтинг: 0 / 0
Заметки о Делфи.
    #709855
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
На днях узнал о синтаксической конструкции в Паскале Делфи, о которой раньше не знал. Смотрел чужой код и натолкнулся на конструкцию
Код: Delphi
1.
&perem
Сначала подумал, что это адрес, в Си, когда параметр передается по ссылке, т.е. передается адрес переменной, то так пишут. Но в Delphi адрес - @. Т.е, чтобы передать адрес, надо написать
Код: Delphi
1.
@perem
Стал искать, не сразу нашел. Оказывается, это другая, довольно специфическая вещь. Имена типов, переменных не должны совпадать с зарезервированными словами языка. Но оказывается, можно ввести идентификатор, совпадающий с зарезервированным словом. Но надо при его объявлении перед ним поставить амперсанд. Тогда парсер кода будет знать, что этот токен не надо трактовать, как зарезервированное слово.
Пример:
Код: Delphi
1.
2.
3.
4.
5.
6.
procedure TForm1.Button1Click(Sender: TObject);
var &begin: integer;
begin
  &begin := 2;
  Caption := IntToStr(&begin);
end;
При использовании (а не объявлении) переменной, можно вместо амперсанда использовать квалифицированное имя переменной: имя модуля - точка - имя переменной.
Код: Delphi
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var
  Form1: TForm1;
  &begin: integer;

...
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  Unit1.begin := 2;
  Caption := IntToStr(Unit1.begin);
end;
Раньше не знал, что есть такая штука.

Но ещё, в коде, где я это увидел, имя переменной не совпадает ни с одним зарезервированным словом. Я предполагаю, что это появилось там в результате ряда ошибок и обстоятельств. Предполагаю. что человек скопировал код из Си. Это функция WinApi, видел пример её использования на Си, там как раз первый параметр передается по ссылке, передается вдрес, и в Си стоит амперсанд. Вероятно человек скопировал этот код и амперсанд тоже. Но в Delphi с одной сторроны адрес пишется @, а с другой - в этой импортированной функции первый параметр объявлен как var-параметр, т.е. он и так уже передается по ссылке, адрес писать не нужно. И в третьих, & в Delphi означает, что имя при парсинге не надо понимать, как зарезервированное слово. Т.е. скопированный так код изменил свой смысл, но так получилось, что результат скомпилировался и он даже правильный. Правда можно просто убрать этот амперсанд, он в данном случае не имеет смысла.
...
Изменено: 24.01.2024, 23:32 - s62
Рейтинг: 0 / 0
Заметки о Делфи.
    #709869
IT-Клоп
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так себе конечно фича...
...
Рейтинг: 0 / 0
Заметки о Делфи.
    #709871
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
IT-Клоп  25.01.2024, 00:33
[игнорируется]
Так себе конечно фича...
Да, согласен. Я просто сначала был озадачен кодом, который увидел, долго (ну относительно) искал, что же такое означает & в паскале делфи. Ну и вот, узнал про такое.
...
Изменено: 25.01.2024, 00:37 - s62
Рейтинг: 0 / 0
Заметки о Делфи.
    #717125
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
В Delphi есть поддержка тем (оформления) Windows. И эта штука, что впрочем логично, не позволяет менять какие-то визуальные свойства тех или иных элементов управления. Например в элементе управления TPageControl: панель с закладками, цвет закладок в теме по-умолчанию в Windows 10 - белый. На белом не всегда хорошо видны поля ввода и т.д. Но цвет, просто задав в design-time какой-то произвольный, не поменяешь, если включена поддержка тем, нарисовано будет всё равно в стиле темы.

Сегодня добавлял в полосу статуса окна (Status bar, полоска внизу), вывод еще одной информации, кроме которой там была. Там несколько панелей, на части выводится текст, на других рисуется типа индикаторов красный/зеленый. Панели есть двух типов - либо задаешь текст и он выводится на панели, либо она отрисовывается программно (свойство Style - psText или psOwnerDraw). И вот надо было добавить ещё одну панельку, в которой выводится текст красным цветом в некоторых ситуациях. Отлаживаю и обращаю внимание, что текстовые панели - жирным шрифтом. Почему? Начинаю искать - в свойствах этого нет, в коде этого тоже нет, из других потоков, которые через Synchronize вызывают разные процедуры в этом окне, тоже нет такого. Причем сначала после открытия окна - без жирного, без bold'а, а потом появляется он. И только через какое-то время догадался, что это - тема. Отключил в опциях проекта поддержку тем и жирный перестал появляться. Ну, потом включил назад. Ладно, раз такая тема, в смысле тема оформления :), то значит так, пусть уж будет, чтобы не выбиваться из стиля Windows.
...
Изменено: 05.02.2024, 18:35 - s62
Рейтинг: 0 / 0
Заметки о Делфи.
    #718871
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Знакомую фамилию увидел. Использовал в коде функцию CompareMem (сравнивает две области памяти), решил глянуть, как она реализована. Ну, как и ряд других функций, взята из проекта Fastcode, вероятно - адаптирована. А среди тех, кто принимал участие в написании, упомянут Александр Шарахов (только он там и упомянут). Александр не раз писал в разделе Delphi на sql.ru.
Цитата 
[игнорируется]
(* ***** BEGIN LICENSE BLOCK *****
*
* The function CompareMem is licensed under the CodeGear license terms.
*
* The initial developer of the original code is Fastcode
*
* Portions created by the initial developer are Copyright (C) 2002-2004
* the initial developer. All Rights Reserved.
*
* Contributor(s): Aleksandr Sharahov
*
* ***** END LICENSE BLOCK ***** *)
...
Изменено: 09.02.2024, 10:19 - s62
Рейтинг: 0 / 0
Заметки о Делфи.
    #721425
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
В индексе TIOBE в феврале на 12 месте:
https://www.tiobe.com/tiobe-index/
...
Рейтинг: 0 / 0
Заметки о Делфи.
    #721426
Неуловимый Джо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[игнорирует гостей]
Висуал бейсик на 9м.
...
Рейтинг: 0 / 0
Заметки о Делфи.
    #724141
IT-Клоп
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Неуловимый Джо  15.02.2024, 08:57
[игнорируется]
Висуал бейсик на 9м.
VB опережает PHP. Ну как такое может быть?
...
Рейтинг: 0 / 0
Заметки о Делфи.
    #724530
Фотография Ифрит
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IT-Клоп  20.02.2024, 12:02
[игнорируется]
Неуловимый Джо  15.02.2024, 08:57
[игнорируется]
Висуал бейсик на 9м.
VB опережает PHP. Ну как такое может быть?
в тиобе, vb, так-то - нет, вроде
под этим названием там другой язык
...
Изменено: 20.02.2024, 20:45 - Ифрит
Рейтинг: 0 / 0
Заметки о Делфи.
    #724535
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
IT-Клоп  20.02.2024, 12:02
[игнорируется]
Неуловимый Джо  15.02.2024, 08:57
[игнорируется]
Висуал бейсик на 9м.
VB опережает PHP. Ну как такое может быть?
У TIOBE какие-то свои методики подсчёта. Там кстати у VB какой-то огромный всплеск, начиная с 2020 года:
https://www.tiobe.com/tiobe-index/visual-basic/

Есть рейтинги на stack overflow:
https://survey.stackoverflow.co/2023/#section-most-popular-technologies-programming-scripting-and-markup-languages
...
Рейтинг: 0 / 0
Заметки о Делфи.
    #729433
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Может все это знают и так, но вдруг кто-то не знает или забыл. Компилятор под Windows использует менеджер памяти, взятый из опенсорсного проекта FastMM. И у него есть такая фишка, он может при закрытии программы показать неосвобожденную память. ОС конечно всю виртуальную память процесса после его закрытия всё равно заберет, но тут можно видеть, какие объекты были созданы и не удалились.
Делается это так: в файле проекта в начале после begin добавляется строчка:
Код: Delphi
1.
2.
3.
4.
begin
  ReportMemoryLeaksOnShutdown := True;
  Application.Initialize;
  Application.CreateForm(TMainForm, MainForm);
Или можно вот так, тогда при запуске под отладчиком будет выводить, а при обычном запуске - нет, т.е. не надо менять код для билдов в продакшен.
Код: Delphi
1.
2.
3.
4.
begin
  ReportMemoryLeaksOnShutdown := DebugHook <> 0;
  Application.Initialize;
  Application.CreateForm(TMainForm, MainForm);
Вот, про настройку менеджера памяти:
https://docwiki.embarcadero.com/RADStudio/Athens/en/Configuring_the_Memory_Manager
...
Рейтинг: 2 / 0
Заметки о Делфи.
    #739599
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Долгое время для измерения времени по-быстрому (хаха, прошу прощения за получившуюся игру слов) использовал функцию win32 API GetTickCount. Эта функция возвращает время в мсек от начала работы компьютера. Результат имеет тип Cardinal (беззнаковое 4 байтовое целое), так что он зацикливается после 49,7 примерно дней работы Windows. (Есть функция GetTickCount64, которая возвращает Int64).
MS пишет:
Цитата 
[игнорируется]
Разрешение функции GetTickCount ограничено разрешением системного таймера, которое обычно находится в диапазоне от 10 до 16 миллисекундах.
Во многих ситуациях этой точности вполне достаточно. Использовал примерно так:
Код: Delphi
1.
2.
3.
4.
5.
6.
7.
8.
9.
var Ticks: Cardinal;

...
  Ticks := GetTickCount;
//тут какой-то код, время исполнения которого измеряем
...
...
//Дальше или выводим куда-то в программе или например пишем в лог
 AddStrToLog(IntToStr(GetTickCount - Ticks));
В последней строчке сначала выполнится GetTickCount, потом вычислится разность, потом выполнится IntToStr и потом AddStrToLog, т.е. во время войдет только то, что мы измеряем, но не время выполнения IntToStr и записи в лог.
Понятно, что тут не учитывается фактор многопоточности, что какое-то время поток, в котором выполняется код, мог спать в то время, когда (если) система выделила кусок (slice) времени другому или другим потокам.

Но в последнее время часто, когда надо померить время, стал использовать точный таймер, для которого есть обертка в Delphi. Обертка в виде записи с методами. У этого таймера период обычно - 0.1 мксек, т.е. частота 10 000 000 гц.
Код: Delphi
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
uses
  System.Diagnostics;

var
  SW: TStopWatch;
...
  SW := TStopWatch.StartNew;
//тут код, время которого измеряем
...
...
  SW.Stop;
//выводим время в мксек
  AddStrToLog(IntToStr(SW.ElapsedTicks * 1000000 div SW.Frequency));
Я обычно писал попроще (но не совсем корректно), т.к. , когда тестирую и измеряю время на рабочей машине, Frequency можно запросить и посмотреть отдельно, а убедившись, что это 10 000 000, обычно писал так:
Код: Delphi
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
uses
  System.Diagnostics;

var
  SW: TStopWatch;
...
  SW := TStopWatch.StartNew;
//тут код, время которого измеряем
...
...
  SW.Stop;
//выводим время в мксек
  AddStrToLog(IntToStr(SW.ElapsedTicks div 10));
TStopWatch - это обертка для функции win32 API QueryPerformanceCounter и сопутствующих функций.
...
Изменено: 19.03.2024, 12:11 - s62
Рейтинг: 1 / 0
Нравится: Ифрит
Заметки о Делфи.
    #788399
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
На старости лет оценил полиморфизм в ООП. На нынешней работе это как-то отчетливо заметно. Программа работает с различным железом. И вот, разные модификации железа, даже разные способы подключения - это означает разные варианты обмена данными. Пока что хорошо решалось тем, что в классе-предке устройства (класс для обмена данными с оборудованием, которое выполняет определенную функцию, а конкретные модели и протоколы обмена могут быть разными) объявляются методы, которые потом будет использовать модуль, использующий эту железку. Часть - с реализацией, где делаются какие-то общие для всех вариантов вещи, часть - абстрактные методы. А в потомках реализуется тот или иной конкретный вариант функций обмена. И в модуле, где они используются, мы в зависимости от настроек, создаем экземпляр того или иного класса(-потомка). А используем методы, объявленные в предке. Буквально сегодня сделал в основном вот такое: раньше использовали через TCP/IP->преобразователь портов->RS-485 один модуль цифровых вводов-выводов, по протоколу DCOM, а сейчас в планах использовать другой модуль того же производителя, с управлением прямо по TCP/IP по протоколу Modbus. И вот была задача добавить работу с ним в программу, чтобы можно было работать или с одним, или с другим. Раньше были просто несколько переменных в модуле, теперь забацал классы.

Ещё - разделение уровней, слоев обмена. За счет этого (писал код, который мне надо было потом модифицировать, другой человек) как-то, при переходе от обмена по одному каналу к нескольким вариантам, пришлось поменять буквально одну функцию, которая отправляла уже подготовленный пакет, в разных реализациях разный 1)по UDP, 2)по USB, 3)по TCP потом преобразователь портов, потом RS-485. Ну не только одну, ещё конструкторы-деструкторы, ещё наверное что-то.
...
Изменено: 23.05.2024, 15:22 - s62
Рейтинг: 2 / 0
Нравится: Гарыныч, Ифрит
Заметки о Делфи.
    #788432
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
s62 [игнорируется] 
Извиняюсь, ошибся. "по протоколу DCOM" - DCON.
...
Рейтинг: 0 / 0
Заметки о Делфи.
    #817024
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Два урока из недавней практики. Известные вещи, но вот.

1) Делать обработку ошибок. Когда-то была большая статья или даже пару статей на эту тему в блоге у gunsmoker. Я, если в среднем, то наверное примерно так: в каких-то ключевых процедурах обработку ошибок типа try ...except пишу, но не во всех подряд процедурах и функциях. Недавно была ошибка, причину которой относительно долго не мог найти. Ошибка была у заказчика, у нас в офисе при работе программ в том же (вроде бы) окружении, как у заказчика, не воспроизводилась. И не сразу локализовал: исключение возникало в процедуре, из которой вызывались другие процедуры. Когда добавил обработку ошибок в них, то выяснилось, что ошибка, исключение возникает в одной из них.

2) Делать проверку входящих параметров. По сети от нашей же программы приходили пакеты заданного формата и вроде как с предопределенным содержанием, в частности кодом (номером) команды из определенного диапазона. Я с программным кодом этой второй программы был знаком, сам там один модуль писал, в другом или паре других делал кое-что. Вроде как должны были послаться только определенные в протоколе команды. Но оказалось, что приходит от неё по сети пакет с кодом (номером) команды, который не предусмотрен протоколом обмена. Из-за некоторых моментов в программном коде этой программы и в её настройках у клиента. Это не проверялось и приводило к некритичным последствия, но, тем не менее, не предусматривавшимся. Добавил проверку корректности кода (=номера) команды - сразу же выяснилось, откуда ошибка, о которой речь в первом пункте.
...
Рейтинг: 0 / 0
Заметки о Делфи.
    #822815
Фотография Ифрит
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
s62  01.07.2024, 14:04
[игнорируется]
1) Делать обработку ошибок. Когда-то была большая статья или даже пару статей на эту тему в блоге у gunsmoker. Я, если в среднем, то наверное примерно так: в каких-то ключевых процедурах обработку ошибок типа try ...except пишу, но не во всех подряд процедурах и функциях. Недавно была ошибка, причину которой относительно долго не мог найти. Ошибка была у заказчика, у нас в офисе при работе программ в том же (вроде бы) окружении, как у заказчика, не воспроизводилась. И не сразу локализовал: исключение возникало в процедуре, из которой вызывались другие процедуры. Когда добавил обработку ошибок в них, то выяснилось, что ошибка, исключение возникает в одной из них.
в try/except, думаю, стоит заворачивать только тот код, где ты знаешь, что исключение возникнуть - может, и - ты знаешь, как его обработать.
иначе это совсем лишняя заморочка. для всех других случаев, и особенно для программ выдаваемых на сторону, можно/стоит использовать, в зависимости от приемлемой лицензии - madExcept (например в PL/SQL Developer встроен), EurekaLog (тот же gunsmoker про неё писал) или набор классов того же функционала из jedi (в последних проектах использовал это решение)
...
Изменено: 11.07.2024, 05:51 - Ифрит
Рейтинг: 1 / 0
Нравится: s62
Заметки о Делфи.
    #823305
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Ифрит  11.07.2024, 05:48
[игнорируется]
s62  01.07.2024, 14:04
[игнорируется]
1) Делать обработку ошибок. Когда-то была большая статья или даже пару статей на эту тему в блоге у gunsmoker. Я, если в среднем, то наверное примерно так: в каких-то ключевых процедурах обработку ошибок типа try ...except пишу, но не во всех подряд процедурах и функциях. Недавно была ошибка, причину которой относительно долго не мог найти. Ошибка была у заказчика, у нас в офисе при работе программ в том же (вроде бы) окружении, как у заказчика, не воспроизводилась. И не сразу локализовал: исключение возникало в процедуре, из которой вызывались другие процедуры. Когда добавил обработку ошибок в них, то выяснилось, что ошибка, исключение возникает в одной из них.
в try/except, думаю, стоит заворачивать только тот код, где ты знаешь, что исключение возникнуть - может, и - ты знаешь, как его обработать.
иначе это совсем лишняя заморочка. для всех других случаев, и особенно для программ выдаваемых на сторону, можно/стоит использовать, в зависимости от приемлемой лицензии - madExcept (например в PL/SQL Developer встроен), EurekaLog (тот же gunsmoker про неё писал) или набор классов того же функционала из jedi (в последних проектах использовал это решение)
EurekaLog и madExcept мощные средства для отладки. И стоят не очень дорого порядка $150, для компании это немного же.
Но есть некоторые моменты. Во-первых, если я правильно понял, EurekaLog, может и второе средство тоже, перехватывают исключение на "верхнем" уровне, примерное как Application.HandleException (который вызывает Application.OnException). Но в каких-то ситуациях хотелось бы перехватить и обработать исключение на более "низком" уровне, в процедуре, где оно возникло, чтобы меньше нарушался ход работы приложения. Ну, это может философский вопрос, может тут можно дискутировать. Но вот другой момент имеет отношение к программе, которой я сейчас больше других занимаюсь.

Программа существенно многопоточная. Она работает с оборудованием, причем может с несколькими установками (на ряде фабрик так и есть). Работа с каждой установкой выполняется в отдельном потоке. Там идет постоянный сетевой обмен, причем не с одной железкой, что-то выводится в БД, есть реакции на возникновение внешних сигналов и наоборот подача сигналов на переключение устройств и т.д. Плюс ещё ряд потоков, какие-то временно создаваемые и потом удаляющиеся, какие-то относительно долго работающие, разные ситуации.

В документации EurekaLog написано, что при работе с доп. потоками, если не обрабатывать исключения, а просто подключить её - это плохой вариант. Хороший вариант - исключения обрабатываются, как положено, а EuricaLog тогда выдаст дополнительную отладочную информацию. Т.е. даже если использовать эти библиотеки, мне все равно нужно как минимум обрабатывать исключения на уровне процедуры TThread.Execute. Да и безотносительно EurecaLog, исключения в потоке нужно обрабатывать в нем. Но там прилично кода, разбитого на ряд процедур и функций и логично на мой взгляд обрабатывать исключения и в них, в частности тогда мы сразу можем более детально локализовать ошибку. В обработчике исключения в лог пишется и имя процедуры, где оно возникло и информация об исключении. И вот до сих пор этого обычно хватало для выявления причин ошибок. Правда во многих случаях была возможность воспроизвести ситуацию в офисе, при работе программы под отладчиком.
Мне кажется, что если писать надежный и переносимый код, то обработка возможных ошибок, в том числе исключений - нужная/полезная вещь. Я где-то использую генерацию исключений в случае каких-то нештатных ситуаций. Естественно, в предположении, что или в этой же функции оно будет обработано, или во внешней функции, вызывающей эту. Один из возможных вариантов. Предугадать, где может возникнуть исключение бывает и сложно заранее. Понятно, что где-то обрабатывать исключения нет смысла, например функции win32 API не генерируют исключения, а возвращают коды ошибок. Но зато твой собственный код в функции, где используется API может привести к какому-нибудь исключению.

Мне кажется эти библиотеки полезны, но они - не панацея, всё равно стоит обрабатывать ошибки в коде программы.
Как-то так.
...
Изменено: 11.07.2024, 21:23 - s62
Рейтинг: 0 / 0
Заметки о Делфи.
    #823442
Фотография Ифрит
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
s62 [игнорируется] 

в доп.потоках, да, припоминаю, там надо самому ловить отдельно, понял
...
Рейтинг: 0 / 0
Заметки о Делфи.
    #823461
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Ифрит [игнорируется] 

А вообще, спасибо, посмотрю джедайские классы. До вчера толком не представлял, что такое EurekaLog. Особо вроде не задумывался, не интересовался, но предполагал, что это что-то для облегчения отладки при работе в среде разработки.
...
Рейтинг: 0 / 0
Заметки о Делфи.
    #835675
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Как поменять местами закладки (TTabSheet) в TPageControl в design time?
Надо открыть Structure view для страницы, там найти PageControl, выделить нужную закладку и наверху есть кнопки - переставить выше или ниже.

И в интернете сейчас увидел, и, если не ошибаюсь, сам так когда-то делал, не зная этой возможности - открывал файл формы в текстовом виде и вручную правил его.
...
Изменено: 29.07.2024, 16:25 - s62
Рейтинг: 0 / 0
Заметки о Делфи.
    #835942
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Поправка:
s62  29.07.2024, 16:25
[игнорируется]
Structure view для страницы
для окна
...
Изменено: 29.07.2024, 22:47 - s62
Рейтинг: 0 / 0
Заметки о Делфи.
    #838870
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Не совсем про Делфи. Надо было из таблицы в программе экспортировать данные в Эксель. Таблица в программе - просто StringGrid, т.е. таблица в окне программы (в программистских обсуждениях называют ещё по переводу с английского - сетка, наверное чтобы не путать с таблицей БД), где в ячейках текст.
Раньше не надо видимо было, но недавно коллега, который работает с программой, начал делать там некоторые манипуляции с данными и ему понадобилось переносить их в Эксель. Из этой таблицы кем-то давно было написано сохранение в текстовый файл, визуально похожее на таблицу, но такое, что эксель открыть это не мог. Я сначала подумал про экспорт через OLE, но не захотел делать этот вариант, жестко завязанный на наличие установленного экселя. Решил сделать экспорт в XML - а XML может импортировать и Эксель, и например LibreOffice Calc, что может пригодиться в связи с импортозамещением. Сделал.
Но тут коллега пишет, что вот бы через копипаст, как из БД. Под "из БД", как я понял, он понимает - из MS SSMS. Я ему ответил:
Цитата 
[игнорируется]
Я посмотрю насчет копирования через буфер обмена. Но там с точки зрения программирования, предполагаю, не так просто, у экселя же свой формат данных. В БД, т.е. в MS SQL Server Management Studio не знаю, как сделано, это же продукт MS. Но почитаю насчет копирования, может не так сложно.
И смутно припоминал, что про экспорт через буфер обмена было в одной давней статье на Королевстве Дельфи. Зашёл, и точно, есть.
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=313

Короче говоря, для экспорта в эксель данных из какой-нибудь таблички можно сделать так. Эксель принимает данные в буфере обмена в формате CSV. Т.е. берем данные, например область, выделенную в таблице. Формируем строку в формате CSV, ячейки разделяем TAB-ом (#9), строки таблицы - LF (#10). отправляем строку в буфер обмена. В Экселе делаем вставку.
...
Изменено: 04.08.2024, 13:52 - s62
Рейтинг: 0 / 0
Заметки о Делфи.
    #838874
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Администратор или Горбатый ёж дай пожалуйста модерку на тему, чтобы удобней редактировать и т.п., если что.
...
Изменено: 02.08.2024, 16:32 - s62
Рейтинг: 0 / 0
Заметки о Делфи.
    #838875
Горбатый ёж
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Пользователь назначен модератором темы: s62.
...
Горбатый ёж:
Пользователь назначен модератором темы: s62.
Рейтинг: 1 / 0
Нравится: s62
Заметки о Делфи.
    #965853
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
В свежей Delphi 12.2 появился класс TParallelArray.

Из записи в блоге. https://blogs.embarcadero.com/faster-delphi-rtl-with-parallel-arrays-and-ordered-dictionaries/
Код: Delphi
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
program ParallelArray;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Classes,
  System.Generics.Collections,
  System.Threading,
  System.Diagnostics;

var
  A1, A2: array of Integer;
  I: Integer;
  T: TStopwatch;

begin
  try
    SetLength(A1, 100_000_000);
    SetLength(A2, 100_000_000);
    for I := 0 to High(A1) do
    begin
      A1[I] := Random(MaxInt);
      A2[I] := A1[I];
    end;

    // Warm up thread pool
    TTask.Create(
      procedure
      begin
        // empty
      end).Start;

    // Serial sorting
    T := TStopwatch.StartNew;
    TArray.Sort<Integer>(A1);
    T.Stop;
    Writeln('TArray.Sort: ', T.Elapsed.ToString);

    // Parallel sorting
    T := TStopwatch.StartNew;
    TParallelArray.Sort<Integer>(A2);
    T.Stop;
    Writeln('TParallelArray.Sort: ', T.Elapsed.ToString);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.
Цитата 
[игнорируется]
If I run it on my main computer, an Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz , I get the following results, a nice 585% improvement! (output trimmed to milliseconds for readability)
Код: Delphi
1.
2.
TArray.Sort: 00:00:16.414
TParallelArray.Sort: 00:00:02.889
Я и не знал, что при помощи класса TArray из System.Generics.Collections можно так сортировать массивы. Там еще есть вот такая сортировка:
Код: Delphi
1.
class procedure Sort<T>(var Values: array of T; const Comparer: IComparer<T>); overload; static;
...
Изменено: 03.10.2024, 11:04 - s62
Рейтинг: 0 / 0
Заметки о Делфи.
    #1019961
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор темы
Видел, как человек пользовался, но как-то сам не обращал внимания. Удобная вещь вверху окна редактора кода - два выпадающих окна, в левом список классов, в правом - список методов выбранного класса. И, как я понял, в нем же, если класс не выбрано - список процедур/функций (не методов классов) этого модуля.
А я всё пользовался поиском и переходом к объявлению (Ctrl+Click). Есть ещё конечно боковое окно структуры модуля, но я им редко до сих пор пользовался, обычно, когда какой-то чужой модуль открывал и искал какие-то классы, методы и т.п., так, оно у меня обычно свернуто.
В одном из текущих проектов есть большие модули с большими классами, где много методов, там эта штука удобна наверное. Всё, сейчас после обеда попробую использовать это.

p.s. Это - часть того, что называется Navigation toolbar, появилось, оказывается в Delphi XE8, я пользовался из этой панели (тулбара) переходом к разным секциям модуля.
https://docwiki.embarcadero.com/RADStudio/Athens//en/Code_Editor#Navigation_Toolbar
...
Изменено: 18.10.2024, 12:15 - s62
Рейтинг: 0 / 0
27 сообщений из 27, показаны все 2 страниц
Форумы / Языки программирования семейства Pascal [закрыт для гостей] / Заметки о Делфи.
Модераторы: s62
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]