Knowledge Base Alert December, 2016







TMS FlexCel for VCL & FMX:

Excel Internal units



Excel uses many different units for measuring different things, and FlexCel uses the same.

For most rendering stuff, including the PDF API, FlexCel uses points, and those is simple: A point is 1/72 of an inch. As you can see in the google calculator here.

A point is also normally used to specify font sizes: For example a font with 10 points has a bounding box of 10/72 inches.

Now, the Excel units are a little more complex. The simplest ones are the y coordinates (rows): A row is measured in 1/20 of an inch. From: http://www.tmssoftware.biz/flexcel/hlp/vcl/index.htm?FlexCel.Core.TExcelFile.GetRowHeight(Int32).htm Returns the current Row height, in Excel internal units. (1/20th of a point)

But the x coordinates (columns) are way more complex. They measure how many “0” you can put in a cell in the font used in the “Normal” style, plus some margins. So, for example, the normal style for an Excel 2007 or newer file is “Calibri 11”, so if you can fit 5 “0”s in a column with that font, (“00000”) then the column width is 5. But not exactly, there are some margins too, which aren’t correctly documented in Excel docs, and which actually change depending in the screen resolution. So the width is not going to be 5, but 5.something. As explained in the help on GetColWidth ( http://www.tmssoftware.biz/flexcel/hlp/vcl/index.htm?FlexCel.Core.TExcelFile.GetColWidth(Int32).htm ) you can convert between columns and rows and pixels using ExcelMetrics.ColMult and ExcelMetrics.RowMult. I wish I could tell you this is an exact science, but sadly Excel isn’t very exact about this. You can see it simply by pressing a screen preview and measuring the real width of a cell, and compare it with what you see on the screen, you’ll see it is not exactly the same.

The actual box width for a cell can also change if you use a different screen scaling: They will look different if you use say 100% or 175% screen scaling. FlexCel can offset this with the property TExcelFile.ScreenScaling ( http://www.tmssoftware.biz/flexcel/hlp/vcl/index.htm?FlexCel.Core.TFlxConsts.RowMult.htm ). While by default this is 100, if you are working always in a different setting, changing this property will make FlexCel work as if it was Excel showing the file at that particular screen scaling. Changes are not much, but they exist so in general it is a bad idea to try to do “pixel perfect” designs in Excel. You always need ot leave some room because in different resolutions the cells might be slightly smaller or bigger.

For more info about how Excel units can change with the resolution, you can also read page 14 of http://www.tmssoftware.biz/flexcel/docs/vcl/UsingFlexCelAPI.pdf (Autofitting Rows and Columns)

TMS TAdvStringGrid:

Associating a unique ID with search list items for TAdvSearchEdit used in TAdvStringGrid



When a TAdvSearchEdit is used as inplace editor in the grid via TAdvSearchEditEditLink, it is often desirable to have associated an unique ID with each item in the searchedit and retrieve this ID upon selection.

The following code demonstrates this for a TAdvSearchEdit used as inplace editor where the unique ID is set via the SearchListItem.Tag property and retrieved when editing ends in the grid.OnCellValidate event:

procedure TForm1.FormCreate(Sender: TObject);
var
  si: TSearchListItem;
begin
  // initialize the search edit
  AdvSearchEditEditLink1.Columns.Add;
  AdvSearchEditEditLink1.CategoryButton.Visible := false;
  AdvSearchEditEditLink1.SearchButton.Visible := false;

 // tag holds the unique value
  si := AdvSearchEditEditLink1.Items.Add;
  si.Captions[0] := 'BMW';
  si.Tag := 1;

  si := AdvSearchEditEditLink1.Items.Add;
  si.Captions[0] := 'Mercedes';
  si.Tag := 2;

  si := AdvSearchEditEditLink1.Items.Add;
  si.Captions[0] := 'Audi';
  si.Tag := 3;
end;

// use the OnGetEditorType event to specify the TAdvSearchEditEditLink as inplace editor:

procedure TForm1.AdvStringGrid1GetEditorType(Sender: TObject; ACol,
  ARow: Integer; var AEditor: TEditorType);
begin
  AEditor := edCustom;
  AdvStringGrid1.EditLink := AdvSearchEditEditLink1;
end;


// retrieve the unique ID of the selected item in the OnCellValidate event:
procedure TForm1.AdvStringGrid1CellValidate(Sender: TObject; ACol,
  ARow: Integer; var Value: string; var Valid: Boolean);
var
  index,t: integer;
begin
  index := (AdvSearchEditEditLink1.GetEditControl as TAdvSearchEdit).SearchList.ItemIndex;
  t := (AdvSearchEditEditLink1.GetEditControl as TAdvSearchEdit).Items[index].Tag;

  // the t variable holds the unique ID of the selected item via the TAdvSearchEdit
end;


TMS TDBAdvGrid:

Doing custom dataset filtering in TDBAdvGrid from the filter edit row



Default, the grid performs built-in filtering of data. It can be desirable to not use the built-in grid filtering but instead perform the filtering directly on the dataset but still use the filter edit UI to enter the filter condition.

To perform the dataset filtering, implement the OnFilterEditUpdate and from this event, set the flag grid.DoAutoEditFilter = false. When this flag is set false, the OnFilterEditDone event will be triggered from where the code can be added to specify the filter.

Example implementation in code with a grid bound to a TADOQuery dataset assuming the filter condition is set in the filter UI for the 'BRAND' or 'TYPE' field in the dataset:

procedure TForm1.FormCreate(Sender: TObject); begin
  adoquery1.SQL.Text := 'SELECT * FROM CARS';
  adoquery1.Active := true;
  dbadvgrid1.FilterEdit.Enabled := true; end; end;

procedure TForm1.DBAdvGrid1FilterEditDone(Sender: TObject; ACol: Integer;
  Condition: string; FilterType: TFilterType); begin
  //event is triggered when built-in filtering is not used and from here custom dataset filtering can be done
  if ACol = BrandColumn then
    adoquery1.SQL.Text := 'SELECT * FROM CARS WHERE BRAND LIKE '''+
Condition+'''';
  if ACol = TypeColumn then
    adoquery1.SQL.Text := 'SELECT * FROM CARS WHERE TYPE LIKE '''+
Condition+'''';
  adoquery1.Active := true;
end;

procedure TForm1.DBAdvGrid1FilterEditUpdate(Sender: TObject; ACol: Integer;
  Condition: string; FilterType: TFilterType); begin
  //just set the flag that built-in filtering will not be used
  DBAdvGrid1.DoAutoEditFilter := false;
end;


TMS VCL WebGMaps:

How to add multiline hint on markers in WebGMaps



You can add a new line by using "\n".

example:

  WebGMaps1.Markers[id].Title:='String 1\nString 2';


TMS TAdvSmoothListBox:

How to add a bubble message list in TAdvSmoothListBox



You can achieve a bubble message list like in a chat-style application by setting:

AdvSmoothListBox.Layout := lblBubble;

Example:


procedure TForm4.FormCreate(Sender: TObject);
var
  it: TAdvSmoothListBoxItem;

begin
  AdvSmoothListBox1.Items.BeginUpdate;

  AdvSmoothListBox1.Header.Fill.Color := RGB(176,188,205);
  AdvSmoothListBox1.Header.Fill.ColorTo := RGB(109,132,162);
  AdvSmoothListBox1.Header.Fill.BorderColor := RGB(45,54,66);
  AdvSmoothListBox1.Fill.Color := RGB(219,226,237);
  AdvSmoothListBox1.Fill.BorderColor := RGB(45,54,66);

  AdvSmoothListBox1.Header.Caption := 'Conversion with Matt';
  AdvSmoothListBox1.Header.Font.Color := clWhite;
  AdvSmoothListBox1.Header.Font.Style := [fsBold];
  AdvSmoothListBox1.Header.Font.Size := 14;
  AdvSmoothListBox1.ItemAppearance.FillAlterNate.Color := RGB(146,216,65);
  AdvSmoothListBox1.ItemAppearance.FillAlterNate.GradientType := gtsolid;
  AdvSmoothListBox1.ItemAppearance.FillAlterNate.ColorMirror := clNone;
  AdvSmoothListBox1.ItemAppearance.FillAlterNate.BorderColor := RGB(146,216,65);

  AdvSmoothListBox1.ItemAppearance.Fill.Color := RGB(211,211,211);
  AdvSmoothListBox1.ItemAppearance.Fill.GradientType := gtsolid;
  AdvSmoothListBox1.ItemAppearance.Fill.ColorMirror := clNone;
  AdvSmoothListBox1.ItemAppearance.Fill.BorderColor := RGB(211,211,211);

  AdvSmoothListBox1.Layout := lblBubble;
  AdvSmoothListBox1.Items.Clear;
  AdvSmoothListBox1.Footer.Visible := False;

  it := AdvSmoothListBox1.Items.Add;
  it.AutoSize := True;
  it.Caption := '<b>Matt</b>';
  it.NotesLocation := plTopLeft;
  it.Notes := 'Hi John, when does the game begin?';

  it := AdvSmoothListBox1.Items.Add;
  it.AutoSize := True;
  it.Caption := '<b>John</b>';
  it.NotesLocation := plTopRight;
  it.Notes := 'Hi Matt, the game begins at 7:30 pm!';

  it := AdvSmoothListBox1.Items.Add;
  it.AutoSize := True;
  it.Caption := '<b>Matt</b>';
  it.NotesLocation := plTopLeft;
  it.Notes := 'Thanks, are you going alone there or with a friend?';

  it := AdvSmoothListBox1.Items.Add;
  it.AutoSize := True;
  it.Caption := '<b>John</b>';
  it.NotesLocation := plTopLeft;
  it.Notes := 'We are travelling with a couple of friends'+#13#10+'If you want, you may join us at 7:00 pm at the parking lot';

  it := AdvSmoothListBox1.Items.Add;
  it.AutoSize := True;
  it.Caption := '<b>Matt</b>';
  it.NotesLocation := plTopLeft;
  it.Notes := 'Ok, I will be there';

  it := AdvSmoothListBox1.Items.Add;
  it.AutoSize := True;
  it.Caption := '<b>John</b>';
  it.NotesLocation := plTopRight;
  it.Notes := 'See you at the parking lot then !';

  it := AdvSmoothListBox1.Items.Add;
  it.AutoSize := True;
  it.Alternate := lbaRight;
  it.Caption := '<b>John</b>';
  it.NotesLocation := plTopRight;
  it.Notes := 'Oh, and do not forget your tickets';


  AdvSmoothListBox1.LookupBar.Visible := False;
  AdvSmoothListBox1.ItemAppearance.HorizontalSpacing := 8;

  AdvSmoothListBox1.Items.EndUpdate;
end;

Result:

KB86



TTMSFMXLiveGrid:

How to sort a TMSFMXLiveGrid by clicking the header of a column



A data-bound TTMSFMXLiveGrid does not support sorting directly, therefore sorting needs to be applied on the dataset itself. To have the desired effect you need to implement the OnCanSortColumn and return Allow := False, then manually sort the dataset which will automatically update the grid and show the values in the sorted order. Changing a value on a sorted dataset will update the value accordingly.

example:

procedure TfrmMain.TMSFMXGrid1CanSortColumn(Sender: TObject; ACol: Integer;
  var Allow: Boolean);
begin
  Allow := false;
//sort on dataset level
end;


TMS FNC UI Pack:

How to launch the webbrowser with an URL or open a file with FNC



Launching the webbrowser with an URL or opening a file in FNC is simple. Add the FMX.TMSFNCUtils / VCL.TMSFNCUtils / LCLTMSFNCUtils unit depending on your IDE and chosen framework.

To launch the webbrowser, use the following code:

TTMSFNCUtils.OpenURL(‘http://www.tmssoftware.com’);

To open a file, use the following code:

TTMSFNCUtils.OpenFile(‘MyFile.txt’);

The way the FNC opens a file differs from operating system to operating system. On desktop operating systems, the file is opened and shown in the default registered application. For mobile operating systems a popup menu is shown that asks in which application the file needs to be opened.

TMS FNC UI Pack:

Using the TTMSFNCBitmapContainer in your applications



TTMSFNCBitmapContainer

The TTMSFNCBitmapContainer is a container for managing and storing images in your application. The images can be added at designtime from a folder by right-clicking the component and choosing "Load files from folder…" or "Add files from from folder...". The latter is used to append images to an already existing image collection.

TTMSFNCBitmapContainer

Most FNC components support the TTMSFNCBitmapContainer to embed images in HTML text or draw images in other non-textual parts. The BitmapContainer property can be used to assign an instance of TTMSFNCBitmapContainer.

TTMSFNCBitmapContainer

When a property in the component refers to a bitmap name you can select from a list of values retrieved from the earlier added collection of images in the TTMSFNCBitmapContainer.

TTMSFNCBitmapContainer

Below you can see a result after applying this on a component that supports the TTMSFNCBitmapContainer.

TTMSFNCBitmapContainer


TTMSFNCURLBitmapContainer

Inheriting from TTMSFNCBitmapContainer is the TTMSFNCURLBitmapContainer component which adds support for downloading an image via an URL. The TTMSFNCURLBitmapContainer has a DefaultImage property that is shown when following the above steps for picking an image in the collection through the Name. As soon as the image is downloaded (asynchronously) the OnDownloadComplete event is triggered which allows you to instruct the component to repaint itself so it displays the updated image.

TTMSFNCBitmapContainer



TMS Aurelius:

My Top 10 Aurelius Features series



After the release of TMS Aurelius Free Edition, the free version of our ORM framework, Wagner Landgraf (TMS Business product manager) has been thinking to do some blog posts about some key TMS Aurelius features. He spent some time deciding what features to show: would they be in chronological order? Separated by categories? In order of "importance" - and what would be the criteria of "importance"? Well, finally, as you can tell from the title of this item, he decided to do that in a "top 10 list" format.

Follow the top 10 Aurelius features series via the overview page at our website or via the BLOG page:


As always, we thank all users for the numerous inputs, feedback, comments and suggestions. This is an invaluable help to steer our developments here at TMS software. We continue to look forward to all your further communications to direct our team to provide you better tools and components for your needs.

Kind regards,
TMS software team
Email: info@tmssoftware.com
Web: http://www.tmssoftware.com
Support, FAQ & Manuals: http://www.tmssoftware.com/site/support.asp


Follow latest developments at tmssoftware.com




NOTICE: If you wish to unsubscribe from the TMS software Newsletter, please click here.