Как вы уже, наверное, в курсе, до 28 сентября при покупке RAD Studio XE3 Вы получаете бесплатный бонусный пакет, содержащий конвертер Mida, премиум-стили для FireMonkey и виновника сегодняшнего поста — компонент (а точнее набор из нескольких компонентов) TMS Grid.
Вчера мне посчастливилось посмотреть, что из себя представляет TMS Grid For Firemonkey и, несмотря на то, что в бонусном пакете отсутствуют исходники, разобраться с работой компонента не составило особого труда, а сам компонент показался мне вполне заслуживающим внимания.
Сравнивать стандартный TGrid с TMSFMXGrid было бы, по-меньшей мере, не совсем корректно, т.к. эти компоненты различаются как небо и земля (хотя оба вроде бы являются сетками), но все-таки в некоторых местах статью я буду ссылаться на возможности TGrid для более полного описания того, что даст нам использование компонента от TMS Software.
Итак, что же входит в состав бонусного пакета от TMS Software. После выполнения setup’а с компонентами на палитре Delphi XE3 появилась новая вкладка «TMS FMX UI», содержащая следующие компоненты:
Соответственно, первый компонент — это сама сетка, а остальные — не визуальные вспомогательные компоненты для расширения возможностей сетки, например, для импорта/экспорта таблиц Excel, создания диалога предварительного просмотра перед печатью таблицы и т.д. Рассмотрим как работают эти компоненты.
Компонент TMSFMXGrid (Сетка)
Если говорить очень кратка, то компонент TMSFMXGrid (без дополнительных компонентов, которые будут рассмотрены ниже) позволяет:
- Вставлять в произвольные ячейки сетки любые компоненты будь то простой CheckBox или TreeView
- Группировать записи в таблице
- Фильтровать записи
- Выделять/Объединять диапазоны ячеек (как в Excel)
- Использовать для произвольных ячеек свои шрифты
- Выводить текст в ячейке под любым углом
- Оставлять комментарии для ячеек (как в Excel)
- и многое другое, в т.ч. и подсвечивать ссылки в ячейках
Создадим проект FireMonkey HD Application и бросим на форму компонент TMSFMXGrid. При настройках по умолчанию наша сетка будет выглядеть точно также как и обычный TStringGrid из VCL:
Как видно на рисунке — для сетки можно задать фиксированные столбцы и строки (через свойства FixedColumns и FixedRows), что является, кстати, выгодным отличием от стандартного грида. Теперь посмотрим, как можно видоизменить и дополнить нашу сетку. Для сложной настройки сетки используется группа свойств Options:
Для начала добавим в нашу сетку «шапку» и «подвал», для этого раскрываем свойства Options.Header и Options.Footer и устанавливаем Visible в значение True. В итоге наша сетка примет следующий вид:
Header и Footer — это простые примитивы типа TRectangle, которые можно использовать для того, чтобы, например, разместить на сетке дополнительные компоненты для фильтрации данных, подписи и т.д.
Также мы можем задать альтернативный цвет строк таблицы, используя вкладку свойств Bands. В отличие от TGrid (у которой есть аналогичное свойство AlternatingRowBackground) здесь мы можем дополнительно указать количество идущих подряд строк с нормальным цветом и альтернативным. Например, на рисунке ниже показана таблица с настроенными свойствами вкладки Bands:
Для столбцов сетки можно включить фильтрацию данных. Для этого используется вкладка свойств Options.Filtering в которой настраиваются необходимые свойства для фильтра. На рисунке ниже представлен внешний вид TMSFMXGrid с включенной фильтрацией данных в столбцах:
Аналогичным образом — буквально в пару кликов мышкой настраиваются и другие свойства TMSFMXGrid: внешний вид и операции над URL, которые вводятся в таблицу, операции для мыши (изменение размеров строк и столбцов, скроллинг и т.д.), настройки экспорта в HTML и т.д.
Теперь посмотрим как можно добавлять в ячейки сетки произвольные компоненты. Пусть, например, в нашей таблице на рисунке выше каждая вторая ячейка в фиксированном столбце будет содержать CheckBox. Для этого можно воспользоваться событием OnGetCellClass, например так:
procedure TForm1.TMSFMXGrid1GetCellClass(Sender: TObject; ACol, ARow: Integer; var CellClassType: TFmxObjectClass); begin if (ACol=0) and((ARow mod 2) <> 0) then CellClassType:=TTMSFMXCheckGridCell; end;
Или воспользоваться методом TMSFMSGrid, в любом месте программы, например, так:
procedure TForm1.Button1Click(Sender: TObject); var i:integer; begin for I := 0 to TMSFMXGrid1.RowCount-1 do if (i mod 2) <> 0 then TMSFMXGrid1.AddCheckBox(0,i); end;
В обоих случаях таблица будет выглядеть одинаково:
Теперь, если мы хотим программно «чекнуть» наш CheckBox достаточно выполнить вот такой код в обработчике OnGetCellProperties:
procedure TForm1.TMSFMXGrid1GetCellProperties(Sender: TObject; ACol, ARow: Integer; Cell: TFmxObject); begin if Cell is TTMSFMXCheckGridCell then TTMSFMXCheckGridCell(Cell).CheckBox.IsChecked:=True; end;
Чтобы отследить изменение состояния CheckBox’а пользователем можно использовать событие OnCellCheckBoxClick:
procedure TForm1.TMSFMXGrid1CellCheckBoxClick(Sender: TObject; ACol, ARow: Integer; Cell: TFmxObject); begin if TTMSFMXCheckGridCell(Cell).CheckBox.IsChecked then ShowMessage('Checked!'); end;
Событие OnCellCheckBoxClick будет вызываться только для ячеек, содержащих CheckBox’ы.
Если нам необходимо вставить в ячейку какой-либо редактор — SpinEdit, DateTmePicker и т.д. мы также можем воспользоваться событием OnGetCellEditorType в котором указать вид редактора для ячейки, например так:
procedure TForm1.TMSFMXGrid1GetCellEditorType(Sender: TObject; ACol, ARow: Integer; var CellEditorType: TTMSFMXGridEditorType); begin case ACol of 1:CellEditorType:=etColorPicker; 2:CellEditorType:=etDatePicker; 3:CellEditorType:=etHexEdit; end; end;
В результате столбцы четки будут содержать следующие редакторы:
TTMSFMXGridEditorType может принимать следующие значения:
Теперь посмотрим как можно группировать записи в ячейках TMSFMXGrid. Вначале наполним нашу таблицу какими-нибудь данными, например так (данные, естественно, взяты наобум):
Теперь нам необходимо сгруппировать все данные в таблице по столбцу «Сайт» и вычислить, скажем, средний рейтинг. С TMSFMXGrid сделать это просто:
TMSFMXGrid1.SortData(1,sdAscending);//указываем столбец для группировки и направление сортировки групп TMSFMXGrid1.Options.Grouping.MergeHeader := true;//заголовок группы будет содержать объединенные ячейки TMSFMXGrid1.Options.Grouping.Summary := true;//показывать под группой строку для вывода обобщенных данных TMSFMXGrid1.Group(1);//группировать данные столбцу с индексом 1 TMSFMXGrid1.GroupAvg(3); //вычислить среднее значение рейтинга (столбец с индексом 3)
После выполнения этого кода наша сетка будет выглядеть так:
Чтобы разгрупировать данные и привести таблицу в первоначальный вид достаточно вызвать метод:
TMSFMXGrid1.UnGroup;
И, раз уж при группировке данных у нас объединялись ячейки таблицы, то заодно посмотрим как ячейки объединяются вручную. Объединить диапазон ячеек можно так:
TMSFMXGrid1.MergeCells(1, 2, 3, 3);
Здесь первые два параметра — это индекс колонки и столбца первой ячейки для объединения, третий и четвертый параметр — количество строк и столбцов для объединения. Выполнение приведенного выше кода приведет к тому, что таблица примет следующий вид:
Теперь, чтобы снова разделить ячейки, достаточно вызвать противоположный Merge метод:
TMSFMXGrid1.SplitCell(1,2);
В Split, соответственно, указывается только первая ячейка объединенного диапазона ячеек.
Что касается диапазонов ячеек в TMSFMXGrid, то диапазон можно получить, выделить/объединить так:
var CR: TCellRange; begin CR:=TMSFMXGrid1.CellRange(2,3,3,2);//задали диапазон TMSFMXGrid1.SelectCells(CR);//выделили диапазон {ИЛИ} TMSFMXGrid1.MergeSelection(CR); //объединили диапазон end;
Что касается работы с отдельной ячейкой сетки, то, как я говорил выше, для ячейки мы можем установить свои шрифты, угол наклона и т.д. Все эти моменты реализованы в виде удобных свойств TMSFMXGrid:
Использование для произвольных ячеек своих шрифтов
TMSFMXGrid1.FontNames[1,1]:='Cooper'; TMSFMXGrid1.FontSizes[1,1]:=16; TMSFMXGrid1.FontColors[1,1]:=TAlphaColorRec.Blue; TMSFMXGrid1.FontStyles[1,1]:=[TFontStyle.fsItalic];
Вывод текста в ячейке под произвольным углом
TMSFMXGrid1.Angles[2,2]:=45;
Добавление комментария к ячейке
TMSFMXGrid1.Comments[3,3]:='111111'; TMSFMXGrid1.CommentColors[3,3]:=TAlphaColorRec.Red;
Кроме рассмотренных выше свойств, методов и событий TMSFMSGrid, этот компонент имеет ещё достаточно много прочих полезных «фишек», например, расчёт сумм по столбцам, рисование на канве ячейки, автоматическое выравнивание ширины столбцов, высот строк и т.д.
Компонент TMSFMXGridRTFIO
Этот компонент предназначен для экспорта таблицы в rtf-документ. В TMSFMXGridRTFIO можно указать начальную строку и столбец для экспорта, а также следующие опции экспорта:
Пример экспорта таблицы в файл:
{настраиваем опции} TMSFMXGridRTFIO1.Options.ExportOverwrite := omAlways; TMSFMXGridRTFIO1.Options.ExportImages := true; TMSFMXGridRTFIO1.Options.ExportBackground := true; {экспортируем и открываем полученный файл} TMSFMXGridRTFIO1.ExportRTF('gridexport.rtf'); XOpenFile('open', 'gridexport.rtf', '', '');
Компонент TMSFMXBitmapContainer
Предназначен для хранения графических файлов и их использования в таблице. Все изображения хранятся в коллекции Items компонента. Вот так можно вставить изображение из коллекции в произвольную ячейку таблицы:
TMSFMXGrid1.AddBitmap(1,7,'Item1'); TMSFMXGrid1.AddBitmap(1,8,'Item2'); TMSFMXGrid1.AddBitmap(1,9,'Item2');
Где первые два параметра — индексы столбца и строки, а третий — имя элемента коллекции (изображения) TMSFMXBitmapContainer для вставки в ячейку.
Компонент TMSFMXGridExcelIO
Компонент для работы с таблицами Excel (*.xls). С помощью этого компонента можно очень легко импортировать таблицу из Excel или экспортировать свою таблицу в файл. Например, я написал такой простой код:
if OpenDialog1.Execute then TMSFMXGridExcelIO1.XLSImport(OpenDialog1.FileName);
Выбрал таблицу со сложным форматированием (прайс-лист) и получил такой вид таблицы в своей программе:
Перенеслись даже изображения, находящиеся в ячейках листа Excel. У TMSFMXGridExcelIO можно настроить следующие свойства:
Компонент TMSFMXGridPrintPreviewDialog
С помощью этого диалога можно сделать предпросмотр таблицы перед печатью. Вызов этого диалога осуществляется точно также как и любого другого:
TMSFMXGridPrintPreviewDialog1.Execute;
С помощью этого диалога можно, например, разбить таблицы по страницам или указать страницы для печати.
Быстродействие
Вполне возможно, что у кого-то после прочтения этого поста возникнет закономерный вопрос — «Как быстро работает этот компонент по сравнению с родными гридами FMX?». Скажу как есть — я сравнивал этот грид только с TStringGrid из FMX и, естественно, TStringGrid при заполнении 6000 ячеек оказался шустрее. Однако и сам TMSFMXGrid выполнил эту же задачу вполне приемлемо — по-крайней мере, по моим субъективным ощущениям скорость работы компонента от TMS Software достаточно высокая.
Что касается итогового мнения по работе с TMS Grid, то лично мне этот компонент очень понравился по своим возможностям. Конечно, я сейчас не рассматривал в статье работу с базами данных (надеюсь, скоро мы узнаем об этом от Александра Божко), но в целом возможности компонента и простота их использования оставили самое положительное впечатление от использования TMS Grid.
Вопрос только один: сколько такая радость будет стоить сама по себе? И стоит ли оно того?
2Алексей, я нашел цену только на весь пакет TMS — 150 евро. Стоит или не покупать? Тут могу только сказать за себя — если бы пришлось собирать проект на FMX и нужна бы была работа с гридом — однозначно бы покупал TMS, потому как родные гриды не идут ни в какое сравнение с этим компонентом.
2G-Sirr, очевидно, что 600 тыс. записей «положат на лопатки» любой компонент FMX, а может даже и не FMX =) На мак-оси не проверял т.к. недавно пришлось убить виртуалку.
2max, ну до Excel ещё далеко, но некоторые полезные мат.функции в компоненте радуют =)
Спасибо за обзор!
А если больше? Скажем, не 6 тыс. записей, а 400? Работают ли хоткеи «из коробки»? Например, Ctrl+A, Ctrl+PageDown и т.п. А как выглядит в MacOS? Ну, и по юзабилити — MacOS все же другой, была ли возможность потестировать?
Целый ексель под руками.
Спасибо Влад, как всегда от тебя исчерпывающая статья.
Позволю себе личное мнение… FireMonkey и даже с TMS пытаются только приблизиться к тому, что уже давно есть… до уровня DevExpres доживем? 600 тыс. записей — детский лепет, есть реально рабатающая СУБД на Delphi, для коннекта — UniDac, более 1 500 000 записей не убивают ни чего………
2zdm: 600 тыс. записей — детский лепет, есть реально рабатающая СУБД на Delphi, для коннекта — UniDac, более 1 500 000 записей не убивают ни чего. Как я понял, представленный компонент осуществляет обработку без СУБД. И в такой постановке функционал действительно очень интересен. По факту очень много реальных задач, для которых использование СУБД для визуализации — это лишнее. Например, когда нужно визуализировать результаты матобработки или данные вытащены с веба. А родных средств для визуализации таких данных очень мало. Когда есть СУБД и данные лежат в БД, то обработка идет в СУБД, и визуализируется только выборка. Естественно для любой современной СУБД… Подробнее »
Поправьте меня если я ошибаюсь. У этого грида поддерживается только одна платформа 32-bit Windows?
Как-то не очень кроссплатформенно получается…
Slike, вроде бы в описании на оф.сайте говорилось о поддержке MacOS…
На оф.сайте да, но по факту, я скачал триальную верcию с http://www.tmssoftware.com/site/tmsfmxpack.asp и у компонентов TMSFMXGrid, TMSFMXEditBtn, TMSFMXEdit Supported Platforms: 32-bit Windows.
Slike, вон оно как..точно. Хм, неужели обманули, демоны? =) Всё-таки настрою я снова виртуалку и проверю как этот грид заработает.
Проверишь отпишись. Думаю интересно будет не только мне.
Влад, посмотрите еще MonkeyStyler https://twitter.com/TheMonkeyStyler/status/251030616215285760
IL, я так понимаю, надо будет сначала лицензию выклянчить на эту утилиту =) что б можно было нормальный обзор сделать.
update: м..ключик пришел в течение пяти минут..
да, что-то я вечно в сторону СУБД :) извиняюсь….
Vlad, автор написал в твиттер, что разошлет всем MVP, и просил написать ему, если кто-то не получил. Буду рад вашему обзору обезьяно-стилизатора ;)
IL, ну я написал ему…теперь вот ковыряюсь в стилях FireMonkey =) Там, кстати, не только обезьяно-стилизатор есть на сайте, но и обезьяно-перекрашиватель :)
Пост уже пишу, но в нем будут не только эти инструменты ;)
Отличный обзор! Спасибо.
Скачал триал и демо…
по гриду есть еще баги, самый неприличный в примере, где в ячейке другая сетка, не удалаяется при скрытии скролбар.
складывается впечатление, что в торопях под тройку переделывали…
Не много в сторону, но всеж… у компаса не нашел свойства отвечающего за поворот стрелки, пришлось шарить стиль — искать там рут стрелки и указывать угол поворота :)
Общее впечатление от компонент положительное, баги не страшны, да и оптимизация под большое количество записей не за горами.
Автору большое Спасибо за статью!!!
Извините не поскажите что это за ошибка и как её решить, не совсем понял как подсоединить этот TMSFMXGridExcelIO.
Создаю Grid, кидаю TMSFMXGridExcelIO, подсоеденяю его, кидаю OpenDialog, а что дальше ?
выбивает при запуске:
[dcc32 Error] E1026 File not found: ‘FMX.EmptySheet.res’
помогите плиз((((
то Денис Гладько:
Проверьте пути к файлам компонент в «Tools->Options…»
а также где реально файл находится.
Vlad и остальные MVP, DevJet объявила, что дарит одну лицензию на все её продукты (в настоящий момент Documentation Insight Enterprise) лично вам навсегда!
https://forums.embarcadero.com/message.jspa?messageID=484095
Кстати, а не добавить ли в темы опросов: каким решением для документирования кода пользуются люди?
2IL
DevJet об этом объявили уже давно на своем сайте :) Я с ними уже говорил и даже обзорчик небольшой сделал про лицензионную версию. Вроде бы ссылка на этот обзор у DevJet на новом сайте висит. Documentation Insight (когда это не обрезанная версия) — отличный инструмент.
Добрый день
Насколько я понял из семинара Embarcadero, в FM робота с данными базы ведется через LiveBinding. Т.е. этот грид просто свяжется с компонентом базы и будут отображать данные (например TCLientDataSet).
Или я неправ?
Nick, я бы не стал употреблять здесь «просто» :), но да — через Visual LiveBinding можно подключить грид к источнику данных и выводить информацию. В случае простеньких таблиц с текстом и числами — работает, а как будет работать с блобами — не знаю, не проверял
Попробуйте перевернуть текст в ячейке на 270 градусов к примеру отформатировать его по вертикали, по горизонтали, а потом экспортировать в эксель. Получим два глюка: 1 — не выравнивается если текст под углом; 2 — при экспорте возникает ошибка именно из-за текста под углом.
Подскажите как отображать все записи таблицы, делаю всё как указано в интернете, но у меня отображается только 200 записей в гриде, хотя в таблице их намного больше.
Combobox в гриде. Если прокрутить скрол или раскрыть и закрыть node список в combobox комкается, выдается ошибка несовместимая с дальнейшей жизнью приложения…