Takmgrid is stringgrid based on Tmstrgrid written by Albrecht Mengel.
This grid was written for Database showing. It containes method to speed
importing data from database and show data in many various manners;

author Oleg Zavgorodnij oleg@mx.snet.ru

Please drop me a message if you use this component and I will continue work on it.
Send me a message about bugs and suggestion. I  

features:
1. Column editor like Tdbgrid:
	a.Column appearance
	b.Titles
	c.Multiple lines in cells
	d.Hiding columns
	e.Checkboxes in cells
	f.Formatting columns (numeric,datetime)
	g.Bevels
2. Sorting
3. Searching
4. Multiple selecting(marking) rows
5. Column names and data access methods
6. Logic of DrawCell, DefaultDrawing, OnDrawDAtacell
7. Methods for filling grid (For example from table)
8. HTML export
9. Variant Vcell property (for non string data manipulation)
10. SYLK export (excel and other spreadsheets read it)
11. Cell arithmetic now!

To do:
1. Help file
2. Support for formula export
3. inplace editors

To install add akmgrid.dcu and strcoled.dcu to component library;

History
1.0a   Help file created
       All major bugs fixed
       SYLK format improved
0.99f cell arithmetic, bug fixed
0.99e Variant properties
      SYLK Format
	  added bevels
0.99d Tons of bugs fixed in saving Columns property
	  Rename some idetifiers from ...field... to ...column...
	  added Column formatting (Display format; numeric and datetime format 
0.99c added HTML export
      added colunm type (checkbox in column)
	  added method fillrowfromdb
	  bug in fillgrid,getcellsindex fixed
0.99b bug in fillgrid fixed

Added following methods and properties to stringgrid:
**************
* Arithmetic *
**************

Now u can set ftformula type of column. Arithmetic support follows
function:
'ARCTAN','COS','SIN','TAN','ABS','EXP','LN','LOG','SQRT','SQR','INT','FRAC',
'CELL','COL','ROW';
CELL(row;col)-value from grid cell[row,col]
COL(col)-value from grid cell[current_row,col]
ROW(row)-value from grid cell[row,current_col]

**************
* Appearance *
**************
COLUMN EDITOR!!! Like TDbGrid Column editor!

  tmcolumn = class(TCollectionItem)
  private
  ...
  protected
  ...
  public
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    function  DefaultAlignment: TAlignment;
    function  DefaultColor: TColor;
    function  DefaultFont: TFont;
    function  DefaultReadOnly: Boolean;
    function  DefaultWidth: Integer;
    procedure RestoreDefaults; virtual;
    property  AssignedValues: tmcolumnValues;
  published
    property  Hide:boolean;
    property  Alignment: TAlignment;
    property  Color: TColor;
    property  ColumnName: String;
    property  Font: TFont;
    property  ReadOnly: Boolean; {NOT WORKING YET}
    property  Title: tmcolumnTitle;
    property  Width: Integer read GetWidth write SetWidth stored IsWidthStored;
  end;



  TakmgridColumns = class(TCollection)
  private
  ...
  protected
  ...
  public
    constructor Create(Grid: Takmgrid; Columnclass: TmColumnClass);
    function  Add: TmColumn;
    procedure RestoreDefaults;
    property Grid: Takmgrid;
    property Items[Index: Integer]: TmColumn;
  end;

Tondrawcell= procedure (Sender: TObject; Col, Row: Longint; Rect: TRect;
                        State: TGridDrawState;var Text:string) of object;


property columns:TakmgridColumns read fcolumns write fcolumns;
property showtitles:boolean read Fshowtitles WRITE setshowtitles default false;

property ondrawcell:tondrawcell read fondrawcell write  fondrawcell;
procedure DefaultDrawText(ACol, ARow: Longint; ARect: TRect;
                          alignvalue:talignment;bevel:TCellBevelStyle;text:string);
procedure DrawCellBevel(ARect: TRect;Raised:boolean);

Ondrawcell is now always working if exists; you can modify canvas and contents 
of Cell (Text in ondrawtext) before showing (for sorting purposes you must keep
numeric and date format but you can chage format of showing text!).
If Defaultdrawing is True then after Ondrawcell default drawcell will be called.
If you set Defaultdrawing to any value in ondrawcell defaultdrawtext will be
take place based on this value and after that dafaultdrawing will be returned
to previous state. This is for individual cells appearance.
 '\n' in cell contents will force showing in multiple lines format;
 'x' in cell display format will force format with decimal separators
 on one vertical line in cell, like this:
     1.1
	 2.34
	12.1

******************
*  Data access   *
******************

property CellByName[name:string;row:integer]:string;
function getcellsname(Acol:integer):string;
function getcellsindex(Columnname:string):integer;

procedure Fillgrid;
TFillNextRecord=procedure (Row:integer;next:boolean) of object;
property  OnFillNextRecord:TFillNextRecord read FFillNextRecord write FFillNextRecord;

Method Fillgrid will call OnFillNextRecord while next is true;

procedure FillrowfromDB(db:tdataset;row:integer);
This method search all Columnnames in dataset equals to columnnames
and fill is by data from dataset; Usefull in OnFillNextRecord with
some self programming of dataset navigating.

property  Vcells[Acol:integer;Arow:integer]:variant read getvcell write setvcell;
property  VCellByName[name:string;row:integer]:variant read getvcellname write setvcellname;
u can now manipulate with non string data

******************
* Selecting Rows *
******************

function GetSelectRow(RowValue,marknumber:integer):Boolean;
procedure SetSelectRow(RowValue,marknumber:integer;Selected:Boolean);
procedure DeSelectAll(marknumber:integer);
function  GetSelectRowCount(marknumber:integer):integer;

With this methods is possible make multiple marks on rows. Marknumber is
index of mark. Selection is not working with SortAllRows and SortAllColumns;

************************************
* Inserting / Deleting / Modifying *
************************************

procedure InsertCols(where,howmuch:Integer);
procedure InsertRows(where,howmuch:Integer);
procedure DeleteCols(where,howmuch:Integer);
procedure DeleteRows(where,howmuch:Integer);
   It does not matter if there are less rows/cols than you want to delete.
procedure AddCol(contents:String;  delimiter:Char);
procedure AddRow(contents:String;  delimiter:Char);
   The contents are splitted into the single cells by the delimiter
function ModifyRow(which:integer; contents,delimiter:string):integer;
   Results in the number of columns
function ModifyCol(which:integer; contents,delimiter:string):integer;
   Results in the number of rows

***********************
* Sorting / Searching *
***********************

The following properties control sorting and searching:

property KeyType:(soString,soStringCaseSensitive,soNumeric,soDate)
   This is the kind, how the keys (and cells) are compared.
   If you work with soNumeric, all non numbers get the same value 0.
      As these zero values would flip in random order a (case insensitive) string sort
      is performed after. So, first come the negatives, then the strings, and thereafter
      the positives.
   Date sorting works with the Delphi StrToDateTime function. It should work with your own
      date format you use (See the Delphi help for the global date format Delphi uses)
property KeyPos:Integer;
property KeyLen:Integer;
   Here you may define, which substring of the cells is used to comparision.
   (Default is KeyPos=1 & KeyLen=MaxInt)
property UseFixed:(hfNot,hfSmart,hfYes);
   hfNot: The fixed rows/columns remain as they are (and are not used in searching)
   hfSmart: When sorting complete rows, the fixed columns are part of the rows and
            change their contents in the same manner as the rows are exchanged.
            The top row (fixed rows) remain intact.
            When sorting complete columns, the fixed rows change and the fixed columns not.
            When sorting (single) row/column, hfSmart protects the fixed part of the row/column.
   hfYes: All sorting includes the fixed columns and rows (as if they were set to 0)
property SortDescending:Boolean;
   false (default) : Ascending sorting order
   true            : Descending sorting order

***********
* Sorting *
***********

procedure SortCompleteColumns(KeyRow:integer);
procedure SortCompleteRows(KeyCol:integer);
procedure SortRow(ThisRow:integer);
procedure SortCol(ThisCol:integer);
procedure SortAllRows;
   The rows are sorted independand
procedure SortAllCols;
   The columns are sorted independand

procedure UndoSort;
  This re-sorts the last sorting.
  Multiple calls of UndoSort have only effect on the last sorting scheme:
   UndoSort;UndoSort -> the sorted order remains.
property SortIndex:TmStrList
  Here you see the actual index. That are the positions, the contents have to be moved
  from, when the undo actions should be made.


*************
* Searching *
*************

Searching can be done with the fixed substrings of cells
   (set SearchSubstring=true and use KeyPos and KeyLen) or
   anywhere in the cells (SearchSubstring=false)
property SearchSubstring:Boolean;

function FindFirst(Key:String; RowWise:Boolean; VAR ResultCol,ResultRow:Integer):Boolean;
    Searches all cells, if UseFixed=hfYes or excludes the fixed cells, if UseFixed=hfNo.
    If UseFixed=hfSmart, then the fixed cols are used if searching rowwise or
                              the fixed rows are used if not searching rowwise.
    All finding methods result in true, when a cell was found.
    If nothing found then ResultCol and ResultRow are set to -1.
function FindFirstInRow(Key:String; searchRow:Integer; VAR ResultCol,ResultRow:Integer):Boolean;
    The same as FindFirst, but only one row is used for searching.
    UseFixed=hfSmart is here the same as hfNo.
function FindFirstInCol(Key:String; searchCol:Integer; VAR ResultCol,ResultRow:Integer):Boolean;
function FindNext(VAR ResultCol,ResultRow:Integer):Boolean;

One can invert the searching direction by the property ReverseSearch. If set to true, then the search
starts at the end. The property may be changed while a search is not ready.
The readonly property SearchExists is set true, if any search was started (and then remains true).
If a search is ready (results in -1,-1) you may invert ReverseSearch. Then the search is started
again at the actual end in the opposite direction and you can get the first result by a FindNext.

A sample searching program:
 if FindFirst('steven',true{rowwise},c,r) then
 repeat memo1.lines.add('Found in cells['+inttostr(c)+','+inttostr(r)+'] = "'+cells[c,r]+'"');
 until not FindNext(c,r);


*******************
* Import / Export *
*******************

procedure takmgrid.SaveasHTML(Title:string;Ontop:boolean;SList: TStrings);
this method creates Slist in HTML format with title Ontop or Bottom;

File can be read to or written from the table as ASCII file.
The second parameter is the column delimiter in every row.
    procedure LoadFromFile(FileName,ColSep:string);
    procedure SaveToFile(FileName,ColSep:String);

The contents of the selected area can be handled with the clipboard:
    procedure CopyToClipboard;
    procedure CutToClipboard;
              Like CopyToClipboard, but empties then selected cells
    procedure PasteFromClipboard;
              Replaces the selected cell rectangle.
              When PasteToCursor is false (default setting),
              not the cursor position is relevant, but the upper left
              corner of the selected area.
    property  PasteToCursor: controls the PasteFromClipboard method:
              When true, the cells are inserted at cursor position.
 The internal format is Tab Delimited Text.

If the property EnableClipboardShortcuts is set to true, and when NOT editing,
you can perform CopyToClipboard by Ctrl-C, CutToClipboard by Ctrl-X,
and PasteFromClipboard by Ctrl-V.

If the property ClickFixed is true the Click Event is called when clicking on fixed rows/cols.
  Col and Row are set to the proper values.
  The implementation is difficult and not yet flickerfree. (Description in the heading of mStrGid.pas)
  As a result of the implementation the OnClick Procedure reads the FixedCols and FixedRows
  values always as zero (They are temporarily set so). This may give some strange behaviour
  in your program - just use SavedFixedCols and SavedFixedRows in the OnClick procedure.
  Also, if clicked the second time at exact the same mouse position in a short time,
  it does not call the click routine. Reason: Your Doubleclick is set too long!
  Remember: property ClickFixed MUST be true.

