Jump to content


Photo

Trouble with adding NxComboColumn at Runtime


  • Please log in to reply
8 replies to this topic

#1 BelangerC

BelangerC

    Senior Member

  • Members
  • PipPip
  • 221 posts
  • Location:Richmond, CA USA
  • Interests:Alternative medicine, programming for

Posted 06 September 2007 - 10:22 PM

Hello:

I'm having a lot of trouble with adding a TNxComboBoxColumn at run time to a NextGrid on a form.

I just updated and did a full clean install of the latest NextGrid component set (4.1.5), including deleting the associated DCP files in the BPL folder.

(BTW, you need to have NxClasses in the USES list to use any VerticalAlignment property setting.)

Here's the basic code I use to test:

I put this in the FormCreate event at the top and then Exit right after before any other processing which has been going on.


var
ACol : TNxCustomColumn;

begin
ACol := GridView1.Columns.Add(TNxComboBoxColumn, 'Test');
ACol.Options := [coEditing];
TNxComboBoxColumn(ACol).Items.Add('One') ;
TNxComboBoxColumn(ACol).Items.Add('Two') ;
TNxComboBoxColumn(ACol).Items.Add('Three') ;

Gridview1.AddRow(5);

exit;
..............................

{other code...}


When I bring up the form, the column shows but there is no dropdown action, nor combobox drop down button. Also, the header click does not fire the Grid's OnHeaderClick event, unlike the other columns (at this time Text, Check Boxes, Dates).

If I create a new app and use the above code, it works fine. (testing to see if it works at all--it does)

If I create a new form to test this in my main app and show the form, it works fine. (testing to see if there is something about the app itself that is affecting this--doesn't seem to be the case.)

If I add the same Uses list to the test form, that test form/grid works fine. (testing to see if there were conflicting units.)

If I add the same below Implementation Uses list to the test form, that test form/grid works fine, i.e. the ComboBox column works as expected.

Apparently, there is something going on in my app's form that is conflicting with the expression of the NxComboBoxColumn.

Do you have any thoughts about what is happening here? I really need this column in my application and the ListColumn will not do, since I need the option to add/edit the list item, which the combobox does.

Thank you for any help you can give,

Chuck Belanger

#2 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 06 September 2007 - 10:31 PM

Hello Chuck,

Maybe problem is in this line:

CODE
  ACol.Options := [coEditing];


Please change it to:

CODE
  ACol.Options := [coEditing, coCanClick, coCanSort];


I hope that this helps, or made a step closer to the solution.

Best regards
boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#3 BelangerC

BelangerC

    Senior Member

  • Members
  • PipPip
  • 221 posts
  • Location:Richmond, CA USA
  • Interests:Alternative medicine, programming for

Posted 06 September 2007 - 11:42 PM

Thank you for the reply.

I actually tried this before and it didn't help. Just to be sure, I just tried using those Option properties again and it did not help. What I found was that [coEditing] was the minimum number of options to make the combobox column work as expected.

It clearly works in a separate, new form, but not in this one. What kind of things would there be that would keep the NxComboBoxColumn from working or for even that matter not firing the OnHeaderClick event?

Although, I added the same USES list to my test form, the test form doesn't actually have the same components on it, thus merely having the unit load may not be enough--Do you think that's where I should be focusing?

If you want, I could send my form's code.

Thanks again,

Chuck Belanger

#4 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 06 September 2007 - 11:48 PM

Hello Chuck,

It will be great if you may send it here.

Please note that coCanClick flag is required for having possibility to click on header. Maybe I can add a new flag coCanHeaderClick to separate this, but maybe this is not related to your problem.

Best regards
boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#5 BelangerC

BelangerC

    Senior Member

  • Members
  • PipPip
  • 221 posts
  • Location:Richmond, CA USA
  • Interests:Alternative medicine, programming for

Posted 07 September 2007 - 12:03 AM

Thanks again.

Yes, the [coCanClick] allows the OnHeaderClick to now work. Although nice, I still need to combobox column to actually work. smile.gif

Here's my cvTable.pas code.

One thing I noticed and it may be different since I originally added it was the need to REGISTER the various column classes at the end of the pas. Is it still necessary to do this?

Anyway, the code is long because the form is not only an editor to create a table and store it in a DB table, but also creates the Grid from the stored information in the table. The grid form is a popup from double clicking on a TreeView node.

Chuck

CODE
unit uCVTable;

interface

uses
{CB: note there are a number of pas files that need to be in the USES list
that the GridView doesn't necesarilly automatically adds:
Columns, ColumnClasses, NxClasses, Grids, Displays, SharedCommon--not sure that the last
three are necessary, but I added them}

//I've had "Source file not found: NxColumns.pas error when the NxColumns
//these are the new Next Grid column names have conflicted with the old names;
// Note: I use the combo box name with the || to make the proper column name
//See: btnAddColClick, line 665, this adds the col type to the table, which
//on reloading calls this col name in error, looking for an old, and now non-
//existent PAS file.

Treeview,
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, wwriched, NxColumns,
wwrichedspellxp, fcStatusBar, ExtCtrls, ToolWin, ImgList,
Menus, XPMan,
VirtualTrees, JclSysUtils, JvExControls, JvComponent,
JvxSlider, GR32_RangeBars, db, IB_Components, uEasysize,
JvCaptionButton, CoolMenu, NxGridPrint, NxEdit, NxColumnClasses,
NxScrollControl, NxCustomGridControl, NxCustomGrid, NxGrid, JvMenus,
NxSharedCommon, mxCaptionBarButtons, NxClasses;

type
TfrmCVTable = class(TForm)
Panel1 : TPanel;
Splitter1 : TSplitter;
Panel2 : TPanel;
fcStatusBar1 : TfcStatusBar;
wwdbTableDoc: TwwDBRichEditMSWord;
GridView1 : TNextGrid;
GridPrint1 : TNxGridPrint;
XPManifest1 : TXPManifest;
MainMenu1 : TMainMenu;
Actions1 : TMenuItem;
TurnOnAutoSize1: TMenuItem;
N1 : TMenuItem;
Print1 : TMenuItem;
N3 : TMenuItem;
Exit1 : TMenuItem;
Edit1 : TMenuItem;
Search1 : TMenuItem;
View1 : TMenuItem;
Footer2 : TMenuItem;
Header2 : TMenuItem;
InputLine2 : TMenuItem;
Indicator1 : TMenuItem;
N4 : TMenuItem;
DisableColumnMoving1 : TMenuItem;
Select1 : TMenuItem;
SelectFullRow2 : TMenuItem;
IndicateSelectedCell1 : TMenuItem;
N5 : TMenuItem;
MultiSelect1 : TMenuItem;
NormalImageList : TImageList;
imlGrid : TImageList;
ImageList2 : TImageList;
ToolBar2 : TToolBar;
btnAddRow : TToolButton;
btnAddCol : TToolButton;
ToolButton10 : TToolButton;
tbClearRows: TToolButton;
ToolButton12 : TToolButton;
tbDeleteRow: TToolButton;
tbDeleteCol: TToolButton;
ToolButton15 : TToolButton;
ToolButton8 : TToolButton;
ToolButton17 : TToolButton;
ToolButton20 : TToolButton;
tbMoveColLeft: TToolButton;
tbMoveColRight: TToolButton;
ToolButton9 : TToolButton;
tbSave2CSV: TToolButton;
tbOpenCSV: TToolButton;
ToolButton1 : TToolButton;
tbExport2HTML: TToolButton;
PrintDialog1 : TPrintDialog;
MakeEditable1 : TMenuItem;
N2 : TMenuItem;
SelectAll1 : TMenuItem;
SelectNone1 : TMenuItem;
N6 : TMenuItem;
DeleteCurrentColumn1 : TMenuItem;
N7 : TMenuItem;
ShowSelectedCount1 : TMenuItem;
InsertColumn1 : TMenuItem;
SelectLastRow1 : TMenuItem;
ToolBar3 : TToolBar;
ToolButton27: TToolButton;
tbEditTableName: TToolButton;
NxTextColumn1: TNxTextColumn;
ToolButton3: TToolButton;
ToolButton4: TToolButton;
Label1: TLabel;
ToolButton5: TToolButton;
SpinEditor1: TNxSpinEdit;
tbVernier: TToolButton;
ToolButton7: TToolButton;
seHeaderHeight: TNxSpinEdit;
Label2: TLabel;
CoolMenu1: TCoolMenu;
cmiActions: TCoolMenuItem;
cmiEdit: TCoolMenuItem;
cmiView: TCoolMenuItem;
cmiSelect: TCoolMenuItem;
capBtnClose: TJvCaptionButton;
capBtnCloneTable: TJvCaptionButton;
FormResizer1: TFormResizer;
qryGetTableRowDescrip: TIB_Query;
popmnuFPHidden: TJvPopupMenu;
LeftFootPedal1: TMenuItem;
MiddleFootPedal1: TMenuItem;
RightFootPedal1: TMenuItem;
procedure FormDestroy(Sender : TObject);
procedure FormCreate(Sender : TObject);
procedure Exit1Click(Sender : TObject);
procedure Print1Click(Sender : TObject);
procedure TurnOnAutoSize1Click(Sender : TObject);
procedure MakeEditable1Click(Sender : TObject);
procedure Search1Click(Sender : TObject);
procedure SelectFullRow2Click(Sender : TObject);
procedure IndicateSelectedCell1Click(Sender : TObject);
procedure MultiSelect1Click(Sender : TObject);
procedure Footer2Click(Sender : TObject);
procedure Header2Click(Sender : TObject);
procedure InputLine2Click(Sender : TObject);
procedure Indicator1Click(Sender : TObject);
procedure DisableColumnMoving1Click(Sender : TObject);
procedure SelectAll1Click(Sender : TObject);
procedure SelectNone1Click(Sender : TObject);
procedure SpinEditor1Change(Sender : TObject);
procedure SelectLastRow1Click(Sender : TObject);
procedure ShowSelectedCount1Click(Sender : TObject);
procedure DeleteCurrentColumn1Click(Sender : TObject);
procedure tbMoveColLeftClick(Sender : TObject);
procedure tbMoveColRightClick(Sender : TObject);
procedure btnAddColClick(Sender : TObject);
procedure InsertColumn1Click(Sender : TObject);
procedure FormShow(Sender: TObject);
procedure GridView1HeaderClick(Sender: TObject; ACol: Integer);
procedure tbEditTableNameClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure GridView1ColumnResize(Sender: TObject; ACol: Integer);
procedure FormCanResize(Sender: TObject; var NewWidth,
NewHeight: Integer; var Resize: Boolean);
procedure GridView1CellFormating(Sender: TObject; ACol, ARow: Integer;
var TextColor: TColor; var FontStyle: TFontStyles;
CellState: TCellState);
procedure tbDeleteColClick(Sender: TObject);
// procedure GridView1SelectCell(Sender: TObject; ACol, ARow: Integer);
procedure GridView1CellClick(Sender: TObject; ACol, ARow: Integer);
procedure GridView1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure GridView1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure tbVernierClick(Sender: TObject);
procedure tbTextAlignLeftClick(Sender: TObject);
procedure GridView1CellColoring(Sender: TObject; ACol, ARow: Integer;
var CellColor, GridColor: TColor; CellState: TCellState);
procedure seHeaderHeightChange(Sender: TObject);
procedure mxCaptionBarButtons1Buttons1Click(Sender: TObject);
procedure GridView1Change(Sender: TObject; ACol, ARow: Integer);
procedure mxCaptionBarButtons1Buttons0Click(Sender: TObject);
procedure GridView1AfterEdit(Sender: TObject; ACol, ARow: Integer;
Value: WideString);
procedure GridView1SelectCell(Sender: TObject; ACol, ARow: Integer);
procedure capBtnCloseClick(Sender: TObject);
procedure GridView1BeforeEdit(Sender: TObject; ACol, ARow: Integer;
var Accept: Boolean);
procedure capBtnCloneTableClick(Sender: TObject);
procedure NxComboBoxColumn1Select(Sender: TObject);
procedure ib_error(Sender: TObject; const ERRCODE: Integer;
ErrorMessage, ErrorCodes: TStringList; const SQLCODE: Integer;
SQLMessage, SQL: TStringList; var RaiseException: Boolean);
procedure popmnuFPHiddenPopup(Sender: TObject);
procedure RightFootPedal1Click(Sender: TObject);
procedure LeftFootPedal1Click(Sender: TObject);
procedure MiddleFootPedal1Click(Sender: TObject);

private
{ Private declarations }

DefDate : string;
//cb: string lists to translate cv_id and col_id into respective Row, Col
//grid coordinates for loading user input data
TableRowList, TableColList : TStringList;

procedure FillFirstCol(Tree: TVirtualStringTree; FirstCol: integer);
procedure SetColProps(Col : integer; ColClass : TNxColumnClass; UseFieldData: boolean);

//below is in SignalOutput now
// procedure TableCellSignalOut(ARow, ACol: integer);
function CheckUserEdits() : boolean;
procedure SaveUserEdits;

public
{ Public declarations }
TableName : string;
ShowTableForm :Boolean; //used to resize in formshow, but no other time
//dynamic array for font color--only way I can store db color and retrieve
//it, unscathed!
ColFontColor : TStringList;

function GetAlignment: TAlignment;

//CB 9/05/07 TVerticalAlignment is "undeclared" after updating
//Its in NxColumns.pas but not accessible; having to assign VA manually

//Turns out I had to completely remove everything, including dcp files
//in Delphi\projects\BPL, and rebuild all packages, then make sure to
//have NxClasses in USES list

function GetVAlignment: TVerticalAlignment;
procedure SetColDefaults(ColClass : TNxColumnClass; ACol: integer);

end;

var
frmCVTable : TfrmCVTable;

implementation

uses uCVSearch, uViewer, Data, DataMod , uColTitle,
uVernierScale, uSaveTableMsg, uUtilities, SignalOutput;

{$R *.dfm}

procedure TfrmCVTable.FormDestroy(Sender : TObject);
begin
//
end;

procedure TfrmCVTable.FormCreate(Sender : TObject);
var
cvVST : TVirtualStringTree;
i, j, x, y, ColID, RowID : integer;
cvTree,ColClass : string;
Data : PNodeData;
Node : PVirtualNode;
ColType : TNxColumnClass;
ACol : TNxCustomColumn;
//v : variant;


begin
//testing:
{
ACol := GridView1.Columns.Add(TNxComboBoxColumn, 'Test');
ACol.Options := [coEditing, coCanClick, coCanSort];
TNxComboBoxColumn(ACol).Items.Add('One') ;
TNxComboBoxColumn(ACol).Items.Add('Two') ;
TNxComboBoxColumn(ACol).Items.Add('Three') ;

Gridview1.AddRow(5);
exit;
}

//cb: something I just learned! If you want a menu on a form you cannot
//select a borderstyle of Dialog; it must be Single or something else.
//mxCaptionButton, doesn't work on bsSingle, or bsToolWindow, or bsSizeToolWindow;
// ok for bsDialog, thus a quandry; trying to use jv caption button
//Yes! looks like jvCaptionButton works with bsSingle, just fine, plus the button
//looks better

//set up string list for Col font colors
ColFontColor := TStringList.Create;

//string list for converting row id (CV_ID) to a row coordinate;
//and col id (CV_TABLE_COL_ID i think) to column coord.
TableRowList := TStringList.Create;
TableColList := TStringList.Create;

GridView1.HeaderStyle := hsAuto;
IndicateSelectedCell1.Enabled := goSelectFullRow in GridView1.Options;
Indicator1.Checked := true;
TurnOnAutoSize1.Checked := true;

//menu changes based on whether in edit/append mode or view mode
ToolBar2.Visible := TV.EditTreeTable ;
//toolbar3 is visible for show or edit of table
//ToolBar3.Visible := TV.EditTreeTable ;

//actually keep actions, but only allow print for when not being edit, but
//used with patient
//Actions1.Visible := TV.EditTreeTable;
TurnOnAutoSize1.visible := TV.EditTreeTable;
Exit1.Visible := TV.EditTreeTable;

MakeEditable1.Visible := TV.EditTreeTable ;
SelectAll1.Visible := TV.EditTreeTable ;
SelectNone1.Visible := TV.EditTreeTable ;
DeleteCurrentColumn1.Visible := TV.EditTreeTable ;
InsertColumn1.Visible := TV.EditTreeTable ;
DisableColumnMoving1.Visible := TV.EditTreeTable ;
MultiSelect1.Visible := TV.EditTreeTable ;

if TV.EditTreeTable then //owner is editing structure of table
begin
TV.CVTableChanges := false;
tbVernier.Enabled := false;
//only have this button visible if showing an old table with data; its
//for moving old data over from a previous session
capBtnCloneTable.Visible := false;
end
else //user is displaying and possibly entering new data into cells
begin
//allows vernier to work with cv table(usually works with a tree)
TV.CVTableVernier := True;
TV.CVTableCellEdits := false;
tbVernier.Enabled := true;
//make sure the Gridview is Readonly when this table is displaying old
//session info
//CurrentSession has the current session id when cv table is called from
//Session History form; otherwise 0; TV.SessionID is the old session id
//being viewed
if Utility.CurrentSession > 0 then
begin
//making gridview readonly doesn't seem to work
//try at Column level
GridView1.ReadOnly := true;
capBtnCloneTable.Visible := true;
tbVernier.Enabled := false;
end
else
begin
GridView1.ReadOnly := false;
capBtnCloneTable.Visible := false;
end;

end;

// ToolBar2.Visible := TV.EditTreeTable ;
// ToolBar3.Visible := TV.EditTreeTable ;

//fill row headers from CV tree
//get which CV tree is active
cvTree :=
'cvVST' +
inttostrzeropad(MainForm.pcCustomView.ActivePageIndex, 2);
cvVST := TV.CurrentCVTree;
// TVirtualStringTree(MainForm.FindComponent(cvTree));

with GridView1 do
begin
GridView1.BeginUpdate;

//only allow column moving in edit mode
if TV.EditTreeTable then
begin
GridView1.Options := (GridView1.Options - [goDisableColumnMoving]);
GridView1.OnHeaderClick := GridView1HeaderClick;
end
else
begin
//use default assigned values (Dates for now)
//GridView1.Options := (GridView1.Options + [goDisableColumnMoving, goUseDefaultValues ]);
GridView1.Options := (GridView1.Options + [goDisableColumnMoving ]);
GridView1.OnHeaderClick := nil;
end;

i:= 0;
//may wish to use a different header, based on type of table
Data := cvVST.GetNodeData(cvVST.FocusedNode);//the focused node is the parent of
//the items which make up the Table

//below was before Folder column was added at Add new table routine; all in db
// Columns.Add(TNxTextColumn, Data.Description);
//with GridView1.Columns[0] do
// SetColProps(i, TNxTextColumn, false);

// GridView1.Columns[0].Options := GridView1.Columns[0].Options + [coAutoSize];
//get table name, documentation, etc
with ModData.qryAnyUse2 do //use a TDataSet for the blob
begin
Close;
SQL.Clear;
SQL.Add('SELECT t.CV_Table_ID, t.TABLE_NAME, t.TABLE_DOC, ');
SQL.Add('t.TABLE_HEIGHT, t.TABLE_WIDTH, t.TABLE_ROWHEIGHT,t.TABLE_HEADERSIZE, ');
SQL.Add('COALESCE(t.TABLE_FIRST_COL_DESCRIP,0) as Table_first_col_descrip ');
SQL.Add('FROM CV_TABLE t ');
SQL.Add('WHERE T.CV_ID = ' + IntToStr(Data.Id) );
//expecting single
Open;
if not EOF then
//store to vars
begin
TV.CVTableID := FieldByName('cv_Table_ID').asInteger;
TableName :=FieldByName('Table_Name').AsString;
TV.CVTableName := TableName;
//set form height and width ; actual setting done in formshow
if FieldByName('Table_Height').asInteger > 0 then
TV.CVTableHeight := FieldByName('Table_Height').asInteger;

//cb: used to know where the first Y column tag comes from; some tables
//have tags longer than 128cc the limit of the node name; can use BLOB

TV.CVTableFirstColDescrip := FieldByName('Table_First_col_Descrip').asInteger;

if FieldByName('Table_Width').AsInteger > 0 then
TV.CVTableWidth := FieldByName('Table_Width').AsInteger;

if FieldByName('Table_RowHeight').AsInteger > 0 then
SpinEditor1.Value := FieldByName('Table_RowHeight').AsInteger
else
SpinEditor1.Value := 16;

if FieldByName('Table_Headersize').AsInteger > 0 then
seHeaderHeight.Value := FieldByName('Table_Headersize').AsInteger
else
seHeaderHeight.Value := 18;

if (FieldByName('Table_Doc').value <> '') or TV.EditTreeTable then
begin
wwDBTableDoc.CopyRichEditFromBlob(FieldByName('Table_Doc'));
if Panel1.Height < wwDBTableDoc.Height then
Panel1.Height := Panel1.Height + wwDBTableDoc.Height;
end
else
begin
//hide doc view/editor
wwDBTableDoc.Visible := false;
//reduce panel height
Panel1.Height := Panel1.Height - wwDBTableDoc.Height;
end;

//make sure doc editor doesn't allow edit for just a view
if not TV.EditTreeTable and wwDBTableDoc.Visible then
wwDBTableDoc.ReadOnly := true;

end;

Close;
end;//qryanyuse2
//now continue adding all columns

//had to use a TDataSet(IBOQuery) for some bizarre reason with IB_query
//when assigning column.width would put dataset at eof

with ModData.qryAnyUse2 do
begin
Close;
SQL.Clear;

//cb: adding new fields to sql, 9/8/06///5/2/07
{
CV_COLUMN_ID DOM_ITEMID NOT NULL,
CV_TABLE_ID DOM_ITEMID,
TABLE_COL_HEADER DOM_SHORTNAME,
TABLE_COL_TYPE DOM_FIRSTNAME,
TABLE_COL_NUMSCALE DOM_SMALLINT,
TABLE_COL_HEADER_IMAGE DOM_SMALLINT,
TABLE_COL_HEADER_ORIENTATION DOM_COL_ORIENTATION,
TABLE_COL_FONT_NAME DOM_FIRSTNAME,
TABLE_COL_FONT_SIZE DOM_SMALLINT,
TABLE_COL_FONT_STYLE DOM_FONTSTYLE,
TABLE_COL_FONT_COLOR DOM_TABNAME,
TABLE_COL_ORDER DOM_SMALLINT,
TABLE_COL_WIDTH DOM_ITEMID,
TABLE_COL_COLOR DOM_TABNAME,
TABLE_COL_TEXT DOM_SHORTDESCRIPTION,
TABLE_COL_TEXT_ALIGN DOM_TABNAME,
TABLE_COL_TEXT_POS DOM_TABNAME,
TABLE_COL_WRAPKIND DOM_SMALLINT,
COL_FILTERTYPE DOM_FILTERTYPE,
CV_OWNER DOM_ITEMID,
OLD_COLUMN_ID DOM_ITEMID
}

SQL.Add('SELECT c.CV_COLUMN_ID, c.CV_TABLE_ID, c.TABLE_COL_HEADER, c.TABLE_COL_TYPE, ');
SQL.Add('c.TABLE_COL_FONT_Size, c.TABLE_COL_FONT_Name, c.TABLE_COL_FONT_Style,');
SQL.Add(' c.TABLE_COL_ORDER, c.TABLE_COL_width, c.Table_Col_Font_color, ');
SQL.Add('c.COL_FILTERTYPE, c.TABLE_COL_HEADER_IMAGE, ');
SQL.Add('c.TABLE_COL_HEADER_ORIENTATION, c.TABLE_COL_COLOR, c.TABLE_COL_TEXT, ');
SQL.Add('c. TABLE_COL_TEXT_ALIGN, c.TABLE_COL_TEXT_POS, c.Table_col_numscale, ');
SQL.Add('c. TABLE_COL_WRAPKIND ');
SQL.Add('FROM CV_TABLE_Columns c JOIN CV_TABLE t ');
SQL.Add('on t.CV_TABLE_ID = c.CV_TABLE_ID ');
SQL.Add('WHERE T.CV_ID = ' + IntToStr(Data.Id) );
SQL.Add('ORDER BY 8 '); //table_col_order
Open;
First;

//cb: colfontcolor array of TColor is a strange work around to set font color
//which can not rely on the property setting for the col font to remain constant
//So, I store it in the array--it works fine.
//I have to remember to change the array if I add or delete a col
//cb: decided to use a TStringList instead, easier to delete and add

//inc(i); //keep at 0

While not EOF do
begin
//set column type, using table_col_type
ColClass := FieldByName('Table_Col_Type').AsString;
ColType := nil;

CASE
Pos(ColClass,'TNxCheckBoxColumn|TNxComboBoxColumn|TNxDateColumn|' +
'TNxImageColumn|TNxIncrementColumn|TNxNumberColumn|TNxProgressColumn|' +
'TNxRateColumn|TNxTextColumn|TNxButtonColumn|TNxGraphicColumn|TNxTreeColumn|'+
'TNxListColumn')
of
1:
ColType := TNxCheckBoxColumn;
19:
ColType := TNxComboBoxColumn;
37:
ColType := TNxDateColumn;
51:
ColType := TNxImageColumn;
66:
ColType := TNxIncrementColumn;
85:
ColType := TNxNumberColumn;
101:
ColType := TNxProgressColumn;
119:
ColType := TNxRateColumn;
133:
ColType := TNxTextColumn;
147:
ColType := TNxButtonColumn;
163:
ColType := TNxGraphicColumn;
180:
ColType := TNxTreeColumn;
190:
ColType := TNxListColumn;
end;

//store the colType to a global var for use in uColTitle
//wow! what a bone head! this global var will end up being the last col
//only. has to be set in headerclick event --Done
// TV.CVTableColTypeClass := ColType;

//there is a persistent column (1st or 0th col) as part of next grid component,
// do not create
//another column, just adjust that first columns properties
if i > 0 then
begin
//cb: 9/5/07 boy! I think I really missed this one, looks like
//I've been adding columns incorrectly, ACol must be initialized, then
//specifically added, Looks like I can get buy with TextColumns, but not
//some of the others, eg ComboBox : I was just using Columns.add

//Well not according to the docs!
// ACol := Columns.Add( ColType, FieldByName('Table_col_Header').asString );
ACol := Columns.Add( ColType );
ACol.Header.Caption := FieldByName('Table_col_Header').asString;
// This adds a duplicate column: Columns.AddColumn(ACol);

end;
//number columns need to be ctFloat by default to accomodate large numbers
//other column classes have unique implied column types ; number cols
//can be integer or float

//looks like you can't assign column type
//How does grid know whether integer or float?

// if ColType = TNxNumberColumn then
// Columns[GridView1.Columns.Count-1].ColumnType := ctFloat;

//set all other column issues with other fields ; true means use the field data
//SetColProps gets all db stored values
SetColProps(i, ColType, true);
//set still other properties as defaults for specific type of column
//SetColDefaults sets non-stored values to standard defaults

SetColDefaults(ColType, i);

// GridView1.Columns[i].Width := GridView1.Columns[i].DefaultWidth;
//GridView1.Columns[i].Options := GridView1.Columns[i].Options + [coAutoSize];
Inc(i);
Next;
end;

Close;
end;

//cb: 4/30/07 two ways to fill the 0th col: as item name or item description
//procedr just below this one

FillFirstCol(cvVST,TV.CVTableFirstColDescrip );


//Get all current cell values; assign to the table cells if present; load
//all into an array, let the array determine if a save must be made

//only load cells for user, not during table structure edit
if not TV.EditTreeTable then
begin
x:=1; //first col (0) filled above with the child nodes, start with 1 (2nd col)
y:=0;
//below just doesn't work
// V := VarArrayCreate([0,1], varInteger);

with ModData.qryAnyUse3 do
begin
SQL.Clear;
//note that the user can only bring up table cell data from the current
//session; he can use the Session History grid to bring up other tables with
//their data. This dataset is all grid cells
SQL.Add('SELECT cv_table_id, cv_column_id, cv_col_row_value, ');
SQL.Add(' CV_id, Ses_id, cv_Table_Ses_id FROM CV_TABLE_SESSIONS ');
SQL.Add('WHERE CV_Table_id = :cvtableid AND ');
SQL.Add('ses_id = :sesid ');
//SQL.Add('ORDER BY CV_TABLE_SES_ID ');
SQL.Add('ORDER BY CV_ID, CV_COLUMN_ID');

Prepare;
ParambyName('cvtableid').AsInteger := TV.CVTableID;
ParambyName('sesid').AsInteger := TV.SessionID;
Open;
First;

////////// trying another way beside Locate the cell info from the dataset
//because Locate just doesn't seem to work correctly; Loop through dataset
//and allocate each record to its corresponding cell--somewhat reverse of
//what I tried initially; there is another way, too: simply do a SQL Select
//for each cell; but this way should be faster since it is limited to just
//the data and the user will probably never fill all cells
while not eof do
begin
RowID :=
TableRowList.IndexOf(IntToStrZeroPad(FieldByName('cv_id').AsInteger,10));

ColID :=
TableColList.IndexOf(IntToStrZeroPad(FieldByName('cv_column_id').AsInteger,10));

GridView1.Cell[ColID, RowID].AsString :=
FieldByName('cv_col_row_value').AsString;

//the array is string, the db has the value stored as a string
//this Array will be used to determine quickly which cells have been
//updated, the record id is stored in the array,too.
TV.CVTableCellArray[ColID,RowID,0] := FieldByName('cv_col_row_value').AsString;
TV.CVTableCellArray[ColID,RowID,1] :=
IntToStrZeroPad(FieldByName('cv_table_ses_id').AsInteger, 10);

Next;
end; //while not eof
CLose;
end; //with qryAnyUse3


////////


{ beginning of original block of code
if not eof then
begin

while y <= GridView1.RowCount - 1 do //rows
begin
RowID := TV.CVTableRowCVID[y];

while x <= GridView1.Columns.Count -1 do //columns
begin
ColID :=
StrToInt(Copy(GridView1.Columns[x].Footer.Caption,1,
Pos('|',GridView1.Columns[x].Footer.Caption)-1) );

//v[0] := RowID;
//V[1] := ColID;

//not sure why, but this is just not working!
ModData.qryAnyUse3.Locate('CV_ID;CV_COLUMN_ID', VarArrayOf([RowID, ColID]),[]);
//ModData.qryAnyUse3.Locate('CV_ID;CV_COLUMN_ID', VarArrayOf([125373, 73]),[]);


if Found then
begin
//what kind of column; how should data be cast?
if GridView1.Columns[x].ColumnType = ctNone then
Cell[x,y].AsString := FieldByName('cv_col_row_value').AsString
else
if GridView1.Columns[x].ColumnType = ctBoolean then
//changing to True/False string
// if FieldByName('cv_col_row_value').AsString = '1' then
if FieldByName('cv_col_row_value').AsString = 'True' then
Cell[x,y].AsBoolean := true
else
//if FieldByName('cv_col_row_value').AsString = '0' then
if FieldByName('cv_col_row_value').AsString = 'False' then
Cell[x,y].AsBoolean := false
else
if GridView1.Columns[x].ColumnType = ctDate then
Cell[x,y].AsDateTime := FieldByName('cv_col_row_value').AsDate
else
if GridView1.Columns[x].ColumnType = ctFloat then
begin
if FieldByName('cv_col_row_value').AsString <> '' then
Cell[x,y].AsFloat := FieldByName('cv_col_row_value').AsFloat
else
Cell[x,y].AsFloat := 0;

end
else
//actually not using integer type for columns, only float to allow
//large numbers, with formatmask limit to truncated number if want to show
//only nearest whole number
//cb: 10/5/06 switching to text col's because I could not get a null cell
//for a float, only a zero

if GridView1.Columns[x].ColumnType = ctInteger then
Cell[x,y].AsInteger := FieldByName('cv_col_row_value').asInteger
else
if GridView1.Columns[x].ColumnType = ctString then
Cell[x,y].AsString := FieldByName('cv_col_row_value').AsString;


//the array is string, the db has the value stored as a string
//this Array will be used to determine quickly which cells have been
//updated, the record id is stored in the array,too.
TV.CVTableCellArray[x,y,0] := FieldByName('cv_col_row_value').AsString;
TV.CVTableCellArray[x,y,1] :=
IntToStrZeroPad(FieldByName('cv_table_ses_id').AsInteger, 10);
end;//found

inc(x);
end; //while x
inc(y);
end; //while y
end; //if not eof then

} //end of original block of code


//Below just could not get around Float type limits, i.e. no display of blank
//value; this is too important in grid; I need to know when the user changes
//a value, including when a null becomes non-null even 0. Otherwise, there will
//end up a record for every cell in the grid that is Float. Whether the user
//actually input data.

{
else //eof, new table no data
begin
//load all cells, especially number columns with blanks; can I override the
//formatmask? NO!
y := 0;
x:= 1;

while y <= GridView1.RowCount - 1 do //rows
begin

while x <= GridView1.Columns.Count -1 do //columns
begin
if GridView1.Columns[x].ColumnType = ctFloat then
GridView1.Cell[x,y].AsFloat := -1
else
GridView1.Cell[x,y].AsString := '';
inc(x);
end;//while x

inc(y);
end; //while y
end;

CLose;
end; //with qryAnyUse3
}

end; //if not TV.EditTreeTable for user's cell data

GridView1.EndUpdate;
end;//gridview
TV.CVTableShow := false;
// StatusBar1.Panels[0].Text := '10 Rows Added';
end;


procedure TfrmCVTable.FillFirstCol(Tree: TVirtualStringTree; FirstCol: integer);
var
Node : PVirtualNode;
i : integer;
Data : PNodeData;
BlobText : string;
AStream : TStringStream;
ARTF : TwwDBRichEditMSWord;

begin

//filling the cells: first the child nodes are in column[0]
Node := Tree.FocusedNode;
//make sure the node.childcount is correct
Tree.ReinitChildren(node,false);

//the 3rd dime is cv_table_ses_id
//This array is to compare cell to array cell to determine whether an SQL
//Update or Insert
SetLength(TV.CVTableCellArray, GridView1.Columns.Count, Node.ChildCount, 2);

SetLength(TV.CVTableRowCVID,Node.ChildCount);

//do a special query for the child nodes for description if so set up
if FirstCol = 1 then
begin
AStream := TStringStream.Create(BlobText);
ARTF := TwwDBRichEditMSWord.Create(nil);
with ARTF do
begin
Visible := false;
//can't use frmCVTable, because it is just being created and has not
//been shown yet; use main app form
Parent := Mainform.Panel1;
Height := 1;
Width := 1;
end;

with qryGetTableRowDescrip do
//get all the children descriptions for their nodes
begin
SQL.Clear;
SQL.Add('SELECT ');
//see TreeView pas for function; returns sql for decryption or not
//depending on TreeView version
SQL.Add(GetSQLDecrip('ml_item_description')+', ');
SQL.Add(GetSQLDecrip('ml_item')+', ');
SQL.Add('cv_has_children, cv_index ');
SQL.Add('from Custom_view cv Join MasterLibrary ml ON cv.ml_id = ml.ml_id');
SQL.Add('Where CV_ParentID = :cvid');
//make sure that you use the same order by clause as DataMod.qryCVByParentid
//The query which gives the data for creating the child nodes

SQL.Add('ORDER BY CV_HAS_CHILDREN, CV_INDEX, ML_item' );

Prepare;
ParambyName('cvid').AsInteger := PNodeData(Tree.GetNodeData(Node)).Id;
Open;
//this just won't be eof, but could be a table template with folder having
//no children; just check each for null
First;

end;//qry
end; //firstcol = 1

i := 0;

with GridView1 do begin

while Node <> nil do
begin

with Tree do
begin

if i = 0 then
Node := Node.FirstChild
else
Node := Node.NextSibling;

if Node <> nil then
begin
Data := GetNodeData(Node);
AddRow;

if FirstCol = 0 then
Cell[0,i].AsString := Data.Description
else
//because this item description may have highlighted text, check for this
//and if so, strip out that description

if FirstCol = 1 then
begin
//cb: so you know, I could use a TDataset qry and use the RTF.LoadFromBlob
//instead of using streams
//At some point it might be nice to have a function that does below; I could
//use this else where

BlobText :=
qryGetTableRowDescrip.fieldByName('ml_item_description').AsString;

//by making position =0 then writing new string, you replace the old string
//not append the new string
AStream.Position := 0;
AStream.WriteString(BlobText);
//this next line turns out to be important!
//my guess is that it determines what part of stream is loaded, i.e. from
//position = 0 on, rather than position (end) on which is null

AStream.Position := 0;
//cannot use next line, i.e. DataString is a read only property
// AStream.DataString :=
// qryGetTableRowDescrip.fieldByName('ml_item_description').AsString;

ARTF.Lines.Clear;
ARTF.Lines.LoadFromStream(AStream);

//signaloutput.pas
//can pass the Blob RTF formatted text asString directly, too.
BlobText :=
ScanHighlightExtract(ARTF.GetRTFText);

//if BlobText = '' then there was no highlighted RTF text, but there can be
//RTF format and that needs to be plain text
if BlobText = '' then
begin
//let the RTF convert the RTF format (if any) to plain text.
BlobText := StripRemnantsRTF(ARTF.Text);
end;

Cell[0,i].AsString := BlobText;
// qryGetTableRowDescrip.fieldByName('ml_item_description').AsString;
end;

TV.CVTableCellArray[0,i,0] := Data.Description;
//actually, with TV.CVTableCellArray, can store the id in the
//array for first column cv_id items from tree
TV.CVTableCellArray[0,i,1] := IntToStrZeroPad(Data.Id,10);

TV.CVTableRowCVID[i] := Data.Id;
//fill row ids in string list to use with IndexOf to get row coord
//for later input data retrieval and assignment
TableRowList.Add(IntToStrZeroPad(Data.Id,10));

if FirstCol = 1 then
qryGetTableRowDescrip.Next;

end; //if Node <> nil
end; //with cvVST//tree

inc(i);
end; //while Node <> nil
end; //with gridview

if qryGetTableRowDescrip.Active then
begin
qryGetTableRowDescrip.Close;
FreeAndNil(AStream);
FreeAndNil(ARTF);
end;

end;


procedure TfrmCVTable.Exit1Click(Sender : TObject);
begin
Close;
end;

procedure TfrmCVTable.Print1Click(Sender : TObject);
begin
if PrintDialog1.Execute then
begin
with GridPrint1 do
begin
RowSize := Gridview1.RowSize * 10;
Print;
end;
end;//execute
end;

procedure TfrmCVTable.TurnOnAutoSize1Click(Sender : TObject);
var
i : Integer;
begin
for i := 0 to GridView1.Columns.Count - 1 do
begin
if TMenuItem(Sender).Checked then
GridView1.Columns[i].Options := GridView1.Columns[i].Options + [coAutoSize]
else
GridView1.Columns[i].Options := GridView1.Columns[i].Options - [coAutoSize];
end;
end;

procedure TfrmCVTable.MakeEditable1Click(Sender : TObject);
var
i : Integer;
begin
for i := 0 to GridView1.Columns.Count - 1 do
begin
GridView1.Columns[i].Options := GridView1.Columns[i].Options + [coEditing];
end;
end;

procedure TfrmCVTable.Search1Click(Sender : TObject);
begin
frmCVSearch.Show;
end;

procedure TfrmCVTable.SelectFullRow2Click(Sender : TObject);
begin
if TMenuItem(Sender).Checked then
GridView1.Options := GridView1.Options + [goSelectFullRow]
else
GridView1.Options := GridView1.Options - [goSelectFullRow];
end;

procedure TfrmCVTable.IndicateSelectedCell1Click(Sender : TObject);
begin
if TMenuItem(Sender).Checked then
GridView1.AppearanceOptions :=
GridView1.AppearanceOptions + [aoIndicateSelectedCell]
else
GridView1.AppearanceOptions :=
GridView1.AppearanceOptions - [aoIndicateSelectedCell];

end;

procedure TfrmCVTable.MultiSelect1Click(Sender : TObject);
begin
if TMenuItem(Sender).Checked then
GridView1.Options := GridView1.Options + [goMultiSelect]
else
GridView1.Options := GridView1.Options - [goMultiSelect];

end;

//cb: columns have footers; but they are used for column properties:
//Column ID, column type if numeric (log, %, VAS, +/-, RDA, COrrection, Affinity
//the last is only used in Pt Registry for setting up Affinity Test threshold
//Also, column filter type (P/F)
//THis menu selection is disabled for now

procedure TfrmCVTable.Footer2Click(Sender : TObject);
begin
if TMenuItem(Sender).Checked then
GridView1.Options := GridView1.Options + [goFooter]
else
GridView1.Options := GridView1.Options - [goFooter];
end;

procedure TfrmCVTable.Header2Click(Sender : TObject);
begin
if TMenuItem(Sender).Checked then
GridView1.Options := GridView1.Options + [goHeader]
else
GridView1.Options := GridView1.Options - [goHeader];
end;

procedure TfrmCVTable.InputLine2Click(Sender : TObject);
begin
if TMenuItem(Sender).Checked then
GridView1.Options := GridView1.Options + [goHeader]
else
GridView1.Options := GridView1.Options - [goHeader];
end;

procedure TfrmCVTable.Indicator1Click(Sender : TObject);
begin
if TMenuItem(Sender).Checked then
GridView1.Options := GridView1.Options + [goIndicator]
else
GridView1.Options := GridView1.Options - [goIndicator];

end;

procedure TfrmCVTable.DisableColumnMoving1Click(Sender : TObject);
begin
if TMenuItem(Sender).Checked then
GridView1.Options := GridView1.Options + [goDisableColumnMoving]
else
GridView1.Options := GridView1.Options - [goDisableColumnMoving];

end;

procedure TfrmCVTable.SelectAll1Click(Sender : TObject);
begin
GridView1.SelectAll;
end;

procedure TfrmCVTable.SelectNone1Click(Sender : TObject);
begin
GridView1.NoSelection;
end;

procedure TfrmCVTable.SpinEditor1Change(Sender : TObject);
var
i: integer;

begin
//below to change row height of selected cell
{
if (GridView1.SelectedRow >= 0) and (GridView1.SelectedRow <
GridView1.RowCount) and (GridView1.RowCount > 0) then
GridView1.RowHeight[GridView1.SelectedRow] := SpinEditor1.AsInteger;
}
//set all rows' height:
GridView1.RowSize := SpinEditor1.AsInteger;
//and change all filled rows (above only changes empty rows)
for i:= 0 to GridView1.RowCount-1 do
GridView1.RowHeight[i] := SpinEditor1.AsInteger;
end;

procedure TfrmCVTable.SelectLastRow1Click(Sender : TObject);
begin
if GridView1.RowCount > 0 then
GridView1.SelectLastRow;
end;

procedure TfrmCVTable.ShowSelectedCount1Click(Sender : TObject);
begin
ShowMessage(IntToStr(GridView1.SelectedCount));
end;

procedure TfrmCVTable.DeleteCurrentColumn1Click(Sender : TObject);
begin
GridView1.Columns.Delete(GridView1.SelectedColumn)
end;

procedure TfrmCVTable.tbMoveColLeftClick(Sender : TObject);
var
o, n, i : Integer;
begin
o := GridView1.Columns[GridView1.SelectedColumn].Position;
n := o - 1;
GridView1.Columns.ChangePosition(o, n);
//re-fill the col font color string list to show changes
for i:=0 to GridView1.Columns.Count-1 do
begin
//not sure I can trust the color to be correct here (see remarks re
//ColFontColor

ColFontColor.Add(ColorToString(GridView1.Columns[i].Font.Color));
end;
end;

procedure TfrmCVTable.tbMoveColRightClick(Sender : TObject);
var
o, n, i : Integer;
begin
o := GridView1.Columns[GridView1.SelectedColumn].Position;
n := o + 1;
GridView1.Columns.ChangePosition(o, n);
//re-fill the col font color string list to show changes
for i:=0 to GridView1.Columns.Count-1 do
begin
//not sure I can trust the color to be correct here (see remarks re
//ColFontColor

ColFontColor.Add(ColorToString(GridView1.Columns[i].Font.Color));
end;
end;

procedure TfrmCVTable.btnAddColClick(Sender : TObject);
var
msg : string;
ColType : TNxColumnClass;
NewId : integer;

begin
{
TNxCheckBoxColumn, TNxComboBoxColumn, TNxDateColumn,TNxImageColumn,
TNxIncrementColumn,TNxNumberColumn, TNxProgressColumn, TNxRateColumn, TNxTextColumn
}

TV.CVTableColType := '';
TV.CVTableColNew := true;
TV.CVTableColTitle := '';

if not Assigned(frmColTitle) then
frmColTitle :=
TfrmColTitle.Create(self);

try
if frmColTitle.ShowModal = mrOK then
begin
//form has its own routine
end;

finally
//OptionsForm.Free; Freed in close of form //NOT ANY MORE
// frmColTitle.Free;
TV.CVTableColNew := false;
end;
{
CheckBox Column
ComboBox Column
Date Column
Image Column
Increment Column
Number Column
Text Number Column
Progress Column
Rate Column
Text Column
Button Column
Graphic Column
Tree Column
}
if TV.CVTableColType <> '' then
//if ComboBox1.Text <> '' then
begin
if TV.CVTableColType = 'CheckBox Column' then
begin
msg := 'CheckBox';
end
else
if TV.CVTableColType = 'ComboBox Column' then
begin
msg:= 'ComboBox';
end
else

if TV.CVTableColType = 'Date Column' then
begin
msg := 'Date';
end
else

if TV.CVTableColType = 'Image Column' then
begin
msg:= 'Image';
end
else

if TV.CVTableColType = 'Increment Column' then
begin
msg:= 'Increment/Count';
end
else

//apparently this no longer exists
{
if ComboBox1.Text = 'TListColumn' then
begin
GridView1.Columns.Add(TListColumn);
msg:= 'List';
end;
}
if TV.CVTableColType = 'Number Column' then
begin
msg:= 'Numeric';
end
else
if TV.CVTableColType = 'Progress Column' then
begin
msg:= 'Progress Bar';
end
else

if TV.CVTableColType = 'Rate Column' then
begin
msg:= 'Rate';
end
else


if TV.CVTableColType = 'Text Column' then
begin
msg:= 'Textual';
end
else

if TV.CVTableColType = 'Text Number Column' then
begin
msg:= 'Text Number';
end
else

if TV.CVTableColType = 'Button Column' then
begin
msg:= 'Button';
end
else
if TV.CVTableColType = 'Graphic Column' then
begin
msg:= 'Graphical';
end
else
if TV.CVTableColType = 'Tree Column' then
begin
msg:= 'Tree';
end;

// SetColProps(GridView1.Columns.Count-1 , ColType, False);
if not TV.CVTableColEditCancel then
begin
ShowMessage('You''ve added a ' + msg +' column.');
TV.CVTreeChanges := true;
end;

end ;

end;

procedure TfrmCVTable.InsertColumn1Click(Sender : TObject);
begin
GridView1.Columns.Insert(TNxTextColumn, 3);
end;


procedure TfrmCVTable.FormShow(Sender: TObject);
begin
ShowTableForm := true;
frmCVTable.Caption := TableName;
//fill pub var with form settings if not in db
if (TV.CVTableHeight + TV.CVTableWidth) = 0 then
begin
TV.CVTableHeight := frmCVTable.Height;
TV.CVTableWidth := frmCVTable.Width;
end;

if TV.EditTreeTable then
begin
frmCVTable.Width := TV.CVTableWidth;
frmCVTable.Height := TV.CVTableHeight;
end
else //for display and not in edit mode, toolbars are invisible, subtract height
begin
frmCVTable.Width := TV.CVTableWidth;
frmCVTable.Height := TV.CVTableHeight- (ToolBar2.Height + ToolBar3.Height);
end;
ShowTableForm := false;
TV.CVTableShow := true;
end;

procedure TfrmCVTable.SetColProps(Col : integer; ColClass : TNxColumnClass;
UseFieldData: boolean);
var
ColWidth, ColID : integer;
ColScale, AddCB : string;
Before_After, cbString : string;
ComboBoxStrings : TStringList;

begin
ComboBoxStrings := TStringList.Create;
cbString := '';

with GridView1.Columns[Col] do
begin
if UseFieldData then
{ 5/2/07
TABLE_COL_HEADER DOM_SHORTNAME,
TABLE_COL_TYPE DOM_FIRSTNAME,
TABLE_COL_NUMSCALE DOM_SMALLINT,
TABLE_COL_HEADER_IMAGE DOM_SMALLINT,
TABLE_COL_HEADER_ORIENTATION DOM_COL_ORIENTATION,
TABLE_COL_FONT_NAME DOM_FIRSTNAME,
TABLE_COL_FONT_SIZE DOM_SMALLINT,
TABLE_COL_FONT_STYLE DOM_FONTSTYLE,
TABLE_COL_FONT_COLOR DOM_TABNAME,
TABLE_COL_ORDER DOM_SMALLINT,
TABLE_COL_WIDTH DOM_ITEMID,
TABLE_COL_COLOR DOM_TABNAME,
TABLE_COL_TEXT DOM_SHORTDESCRIPTION,
TABLE_COL_TEXT_ALIGN DOM_TABNAME,
TABLE_COL_TEXT_POS DOM_TABNAME,
TABLE_COL_WRAPKIND DOM_SMALLINT,
COL_FILTERTYPE DOM_FILTERTYPE,
}

with ModData.qryAnyUse2 do
begin
//cb: 5/2/07 there are 2 other kinds of word wrap, but these are most
//common, + with hint on; WordWrap kind is for use of long cell item names
//as from BLOB text fields; see uColTitle setting for use of Item Name
//vs Item Description

if FieldByName('TABLE_COL_WrapKind').asInteger = 0 then
WrapKind := wkEllipsis
else
if FieldByName('TABLE_COL_WrapKind').asInteger = 1 then
WrapKind := wkWordWrap;

if FieldByName('TABLE_COL_TEXT_ALIGN').asString = 'LEFT' then
Alignment := taLeftJustify
else
if FieldByName('TABLE_COL_TEXT_ALIGN').asString = 'RIGHT' then
Alignment := taRightJustify
else
if FieldByName('TABLE_COL_TEXT_ALIGN').asString = 'CENTER' then
Alignment := taCenter;

if FieldByName('TABLE_COL_TEXT_POS').asString = 'TOP' then
VerticalAlignment := TVerticalAlignment(vaTop) //vaTop conflicts with TJvVerticalAlignment
else
if FieldByName('TABLE_COL_TEXT_POS').asString = 'BOTTOM' then
VerticalAlignment := TVerticalAlignment(vaBottom)
else
if FieldByName('TABLE_COL_TEXT_POS').asString = 'MIDDLE' then
VerticalAlignment := TVerticalAlignment(vaMiddle);

//setting Color is not enough, see gridview.onCellColoring too

Color := StringToColor(FieldByName('TABLE_COL_COLOR').asString);

//looks like one cannot set header color (probably an XP manifest thing!)
// Header.color := clSkyBlue;
Header.Caption := ModData.qryAnyUse2.FieldByName('Table_col_Header').asString;

if FieldByName('TABLE_COL_HEADER_ORIENTATION').asString = 'HORIZONTAL' then
Header.Orientation := hoHorizontal
else
if FieldByName('TABLE_COL_HEADER_ORIENTATION').asString = 'VERTICAL' then
Header.Orientation := hoVertical;

Font.Name := FieldByName('TABLE_COL_FONT_NAME').asString;

//cb: Wierd! need OnCellFormating.TextColor setting, even then someplace
//between here and there, color gets changed
Font.Color := StringToColor(FieldByName('TABLE_COL_FONT_COLOR').asString);
//using an array to store column color for font instead
ColFontColor.Add(FieldByName('TABLE_COL_FONT_COLOR').asString);

Font.Style := [];
Font.Size := FieldByName('TABLE_COL_FONT_SIZE').AsInteger;
end
else
begin
//not using the stored values (i.e. a new column), use defaults
Alignment := taCenter;
VerticalAlignment := TVerticalAlignment(vaMiddle);
Color := clWhite;
Header.Caption := '';
Header.Orientation := hoHorizontal;
Font.Name := 'Arial';
Font.Color := clBlack;
Font.Style := [];
Font.Size := 10;
end;


Header.Alignment := taCenter;//taLeftJustify; //
//Only show hint during edit process

if TV.EditTreeTable then
Header.Hint := 'Click to edit column and header properties.'
else
Header.Hint := '';

{
Header.DisplayMode := dmImageOnly; dmTextOnly; dmTextAndImage
}
//hoVertical; //
//Gridview1.HeaderSize := 50;


if UseFieldData then
with modData.qryAnyUse2 do
begin
//set both default and width as the same ;

ColWidth := FieldByName('Table_col_width').AsInteger;
GridView1.Columns[Col].DefaultWidth := ColWidth;

//Width needs explicit reference, otherwise ambiguous with form.
//there is something about next line that moves the dataset to eof!???
//OK if using a TDataSet, not ib_query
GridView1.Columns[Col].Width := ColWidth;
//TNxCustomColumn( GridView1.Columns[Col]).Width := ColWidth;

//set a default width if none
if GridView1.Columns[Col].Width = 0 then
GridView1.Columns[Col].Width := 100;

//store record id in footer caption (footer not used now) to know which col = which rec
//Store Col FilterType in footer, too; cb: 10/2/06 adding column type, if numeric
//to determine the type of scale the vernier will show by default

ColID := FieldByName('CV_COLUMN_ID').asInteger;

//ColID should always be > 0
if ColID > 0 then
begin
Footer.Caption := IntToStr(ColID) + '|' +
FieldByName('Col_FIlterType').AsString;
//fill stringlist for use in retrieving the user data input
TableColList.Add(IntToStrZeroPad(ColID,10));

//if null then a zero
//colscale = '', 0, 1-7 at this point
// 0 is reserved for the cast of this field, i.e. it is null
//1 = log
//2 = percent
//3 = VAS 0-10
//4 = -/+ 100
//5 = corrections scale 1-10billion
//6 = affinity threshold scale, not used out side of patient registry
//7 = RDA of vitamins, etc (not implemented yet)
//8 = like 5 but with units of centuries, for NMT ASTMP

//Note: to not display the TextAfter/Before in a blank cell, see my modification
//NxDisplays.pas L1297, TTextualColumnDisplay.Paint;
{
with Column as TNxTextColumn do
//cb: 10/4/06 do not put out text after/before if value is null
if AsString <> '' then
DrawTextRect(TextBefore + AsString + TextAfter, GetTextRect)
else
DrawTextRect( AsString , GetTextRect)
}
//AND
//NxColumnClasses. TNxTextColumn.GetDisplayText, L748

//set Items property of combo box type column
if FieldByName('Table_Col_Type').AsString = 'TNxComboBoxColumn' then
begin
cbString := FieldByName('TABLE_COL_TEXT').AsString;

while pos(#13#10,cbString) > 0 do
begin
AddCB := Copy(cbString,1,pos(#13#10,cbString)-1);
ComboBoxStrings.Add(AddCB);
cbString := Copy(cbString,pos(#13#10,cbString)+2,maxint);
end;
//get the last of the string, it wont have CR
ComboBoxStrings.Add(cbString);
with GridView1 do
with TNxComboBoxColumn(Columns[Col]) do
begin

Items.AddStrings(ComboBoxStrings);
//everything else set in SetColDefaults procedure
end;//with gridview1
end;
{
//cb: 10/4/06 do not put out text after/before if value is null
if Value <> '' then
Result := FTextAfter + Value + FTextBefore
else
Result := Value;
}

Before_After := '';

if (FieldByName('Table_Col_Type').AsString = 'TNxNumberColumn') or
(FieldByName('Table_Col_Type').AsString = 'TNxTextColumn') then
begin
ColScale := FieldByName('Table_Col_NumScale').AsString;

if Pos('|',FieldByName('TABLE_COL_TEXT').AsString)>0 then //could be before or following
begin
if Pos('|F',FieldByName('TABLE_COL_TEXT').AsString)>0 then
begin
Before_After :=
Copy(FieldByName('TABLE_COL_TEXT').AsString,1,
POS('|F',FieldByName('TABLE_COL_TEXT').AsString)-1);
if (FieldByName('Table_Col_Type').AsString = 'TNxNumberColumn') then
TNxNumberColumn(GridView1.Columns[Col]).TextAfter := Before_After
else
if (FieldByName('Table_Col_Type').AsString = 'TNxTextColumn') then
TNxTextColumn(GridView1.Columns[Col]).TextAfter := Before_After;

end
else
if Pos('|B',FieldByName('TABLE_COL_TEXT').AsString)>0 then
begin
Before_After :=
Copy(FieldByName('TABLE_COL_TEXT').AsString,1,
POS('|B',FieldByName('TABLE_COL_TEXT').AsString)-1);
if (FieldByName('Table_Col_Type').AsString = 'TNxNumberColumn') then
TNxNumberColumn(GridView1.Columns[Col]).TextBefore := Before_After
else
if (FieldByName('Table_Col_Type').AsString = 'TNxTextColumn') then
TNxTextColumn(GridView1.Columns[Col]).TextBefore := Before_After;

end;
end;
end
else //'TNxNumberColumn'
ColScale := ''; //integer 1-7 for now

Footer.Caption := Footer.Caption + '#' + ColScale
end; //ColID > 0

Font.Color := TColor(FieldByName('Table_col_font_color').AsSTring);
if Font.Color = clNone then
Font.Color := clBlack;

Font.Name := FieldByName('Table_col_font_name').AsString;
if Font.Name = '' then
Font.Name := 'Arial';

Font.Size := FieldByName('Table_col_font_size').AsInteger;
if Font.Size = 0 then
Font.Size := 10;

//Font.Style := TFontStyles('[' +
//TFontStyle(FieldByName('col_font_style').value) + ']');
//Font.Style := TFontStyles('[' + FieldByName('col_font_style')+']');
Font.Style := [];
end
else
begin
DefaultWidth := 100;
Font.Color := clBlack;
Font.Name := 'Arial';
Font.Size := 10;
Font.Style := [];
end;

// Header.Column.
// Header.Color := clRed; this doesn't work in XP
GridView1.HeaderStyle := hsAuto;
//GridView1.HeaderSize := 24;
//the "options" used alone evokes form Options in compile
if TV.EditTreeTable then
begin
//add these for editing
GridView1.Columns[Col].Options := [coCanClick, coEditing, coCanInput, coSearchColumn];
//remove these
GridView1.Columns[Col].Options := GridView1.Columns[Col].Options -
[coCanSort];
end
else
begin
if Utility.CurrentSession > 0 then
begin
GridView1.OnCellClick := nil;
GridView1.OnSelectCell := nil;

//do not allow editing or input
//below does not stop editing of cells/columns;
//nor does simply GridView1.ReadOnly=true;

//add these options
GridView1.Columns[Col].Options := [coFixedSize, coSearchColumn];
//remove these options
GridView1.Columns[Col].Options := GridView1.Columns[Col].Options -
[coCanClick, coEditing, coCanInput, coCanSort];
end
else
GridView1.Columns[Col].Options := [coCanClick, coEditing, coCanInput, coFixedSize, coSearchColumn];
end;

Position := Col;
Sorted := false;
VerticalAlignment := TVerticalAlignment(vaMiddle);

if ColClass = TNxCheckBoxColumn then
Alignment := taCenter
else
if ColClass = TNxTextColumn then
Alignment := taLeftJustify
else
Alignment := taRightJustify;

end; //columns
ComboBoxStrings.Free;

end;


procedure TfrmCVTable.GridView1HeaderClick(Sender: TObject; ACol: Integer);
begin
//can't edit the left most header, because it is the folder name
//We can now!
if TV.EditTreeTable then //AND (ACol <> 0)
begin
//use this event to allow editing of the Header title
//cb: and now the Signal output/filter type Prefix, Suffix, None
//cb: 9/8/06 expanding dlg to include all aspects of column and header

//passing the column number to a global var for use in form
//ACol is zero based
TV.CVTableCol2Edit := ACol;
TV.CVTableColID2Edit := StrToInt(Copy(GridView1.Columns[ACol].Footer.Caption, 1,
POS('|',GridView1.Columns[ACol].Footer.Caption)-1));

//TV.CVTableColTypeClass := Do not use this, it is set correctly in ColTitle
//but not in cvTable


if not Assigned(frmColTitle) then
frmColTitle :=
TfrmColTitle.Create(self);

try
TV.CVTableColTitle := GridView1.Columns[ACol].Header.Caption;
TV.CVTableColFilterType :=
Copy(GridView1.Columns[ACol].Footer.Caption,
Pos('|',GridView1.Columns[ACol].Footer.Caption) + 1, MaxInt);

if frmColTitle.ShowModal = mrOK then
begin
//see btnOK.click in uColTitle form; a number of property settings come
//from the form's components.


end;
finally
//application.ProcessMessages;
//OptionsForm.Free; Freed in close of form //NOT ANY MORE
//FreeAndNil(frmColTitle); //.Free;
// frmColTitle.Free;

//ColTitle form freed/nil in its own Close event, otherwise getting an
//AV doing it this way
application.ProcessMessages;
end;
end;//if TV.edittreetable
end;


procedure TfrmCVTable.tbEditTableNameClick(Sender: TObject);
begin
//I've loaded the current table name into tv.cvtablename, use that
if MainForm.ShowCVTableName then
begin
with ModData.dsql_AnyUse do
begin
SQL.Clear;
SQL.Add('UPDATE CV_TABLE ');
SQL.Add('SET TABLE_NAME = ' + #39 + TV.CVTableName + #39 );
SQL.Add('WHERE CV_TABLE_ID = ' + IntToStr(TV.CVTableID) );
ExecSQL;
Moddata.IB_Transaction1.Commit;
end;
end;
end;

procedure TfrmCVTable.FormClose(Sender: TObject; var Action: TCloseAction);
var
i: integer;
ParentNode : PVirtualNode;
Data : PNodeData;

begin
//save any form resizing
//save on each close, no need to check for any modifications
//if TV.EditTreeTable and ((TV.CVTableHeight <> frmCVTable.Height) or
//(TV.CVTableWidth <> frmCVTable.Width)) then

if TV.EditTreeTable then
with ModData.dsql_AnyUse do
begin
SQL.Clear;
SQL.Add('UPDATE CV_TABLE ');
//this height includes the invisible toolbars, subtract when displaying
SQL.Add('SET TABLE_Height = ' + IntToStr(frmCVTable.Height) );
SQL.Add(', Table_Width = ' + IntToStr(frmCVTable.Width) );
SQL.Add(', Table_RowHeight = ' + IntToStr(SpinEditor1.AsInteger) );
SQL.Add(', Table_Headersize = ' + IntToStr(seHeaderHeight.asInteger) );

//next field determines whether first col uses Node name or Item description
SQL.Add(', Table_First_Col_Descrip = ' + IntToStr(TV.CVTableFirstColDescrip));
SQL.Add('WHERE CV_TABLE_ID = ' + IntToStr(TV.CVTableID) );
ExecSQL;
Moddata.IB_Transaction1.Commit;
end;
//check for any col position change and update db
if TV.EditTreeTable then
with ModData.qryAnyUse2 do
begin
Close;
SQL.Clear;
SQL.Add('SELECT c.CV_COLUMN_ID, c.TABLE_COL_ORDER ');
SQL.Add('FROM CV_TABLE_Columns c ');
SQL.Add('WHERE c.CV_TABLE_ID = ' + IntToStr(TV.CVTableID) );
SQL.Add('ORDER BY 1 ');
Open;

//first col is the folder children items and not used; nor allowed to change
//position
for i:= 1 to GridView1.Columns.Count - 1 do
begin
if Locate('cv_column_id',
StrToInt(Copy(GridView1.Columns[i].Footer.Caption,1,
Pos('|',GridView1.Columns[i].Footer.Caption)-1)),[]) then
//if Found and (FieldByName('Table_col_order').AsInteger <> i + 1) then
// if Found then //looks like I need to set every rec
begin
edit;
FieldByName('Table_col_order').AsInteger := GridView1.Columns[i].Position +1 ;
post;
end;
end;
//ModData.IB_Transaction1.Commit;
Close;
end;//qry

//if changes to wwDBTableDoc then save them
if TV.EditTreeTable and wwDBTableDoc.Modified then
begin
with ModData.qryAnyUse2 do
begin
SQL.Clear;
SQL.Add('SELECT TABLE_DOC FROM CV_Table ');
SQL.Add('WHERE CV_TABLE_ID = ' + IntToStr(TV.CVTableID) );
Open;
if not EOF then //expecting singleton
begin
edit;
wwDBTableDoc.CopyRichEdittoBlob(FieldByName('table_doc') );
post;
end;
Close;
end;//qryAnyUse2
end; //TV.EditTreeTable and wwDBTableDoc.Modified

//save user entries and nil the array
//cb: cannot totally rely on TV.CVTableCellEdits, since this
//is not changed for numeric cells, I would need an OnExitCell event
//to catch changes, but I can catch any change here by comparing to the
//grid array, TV.CVTableCellArray to the actual grid cells


//if not TV.EditTreeTable and TV.CVTableCellEdits then
if not TV.EditTreeTable and (TV.TreeViewMode = 'CLIENTS') then
begin

//hide vernier if showing
if frmVernierScale.Visible then
frmVernierScale.Hide;

//if TV.CVTableCellEdits then for sure at least one change
//SaveUserEdits will change TV.CVTableCellEdits to false if CVTable is
//for display of previous session values

if TV.CVTableCellEdits then
SaveUserEdits
else
begin
//check for any changes, if so then do saveuser edits
TV.CVTableCellEdits := CheckUserEdits(); //function just below
if TV.CVTableCellEdits then
SaveUserEdits;
end;

//if any changes to table then note the session action, Opened and edited a table
if TV.CVTableCellEdits then
begin
ParentNode := TV.CurrentCVTree.FocusedNode;
Data := TV.CurrentCVTree.GetNodeData(ParentNode);
StoreSesAction('TABLEOPEN', Data.Id);
end;

//if coming from session history replace current session
if Utility.CurrentSession > 0 then
begin
TV.SessionID := Utility.CurrentSession;
Utility.CurrentSession := 0;
GridView1.ReadOnly := False; //doesn't actually make the grid read only
end;

//nil the array
TV.CVTableCellArray := nil;
TV.CVTableRowCVID := nil;
TV.CVTableVernier := false;
end;//user changes

TV.CVTableName := '';
TV.CVTableID := 0;
TV.CVTableWidth := 0;
TV.CVTableHeight := 0;

TV.CVTableShow := false;

ColFontColor := nil;
TableRowList := nil;
TableColList := nil;

end;

//exit routine with TRUE on first cell which shows its been edited by user
{
ctNone No type for cells specified
ctBoolean Cells in this column are in Boolean type : 0/1 //True/False now
ctDate Cells in this column are in DateTime type : numeric storage
ctFloat Cells in this column are in Double type : numeric

ctInteger Cells in this column are in Integer type : numeric
ctString Cells in this column are in String type : string, no conversion needed
}

function TfrmCVTable.CheckUserEdits() : boolean;
var
i, j: integer;
HasEdit : boolean;

begin
HasEdit := false;

for i:= 0 to GridView1.Columns.Count-1 do
begin
if i= 0 then Continue; //skipping the first, column which is not editable
//because it is the child nodes of the tree, nothing to input by user
for j:= 0 to GridView1.RowCount-1 do
begin
{
if (GridView1.Columns[i].ColumnType = ctInteger) or
(GridView1.Columns[i].ColumnType = ctFloat)
then
begin
}
//if (GridView1.Cell[i,j].AsString <> '') and
//(StrToInt(GridView1.Cell[i,j].AsString) <>
//StrToInt( TV.CVTableCellArray[i,j,0])) then

//You know I do not need to differentiate the cell types, just compare
//the asString value
//Note: cell value does not include the TextAfter/Before
if GridView1.Cell[i,j].AsString <> TV.CVTableCellArray[i,j,0] then
begin
//eliminate saving dates of '12/30/1899' or False for boolean type
if (GridView1.Columns[i].ColumnType = ctBoolean) and
(GridView1.Cell[i,j].AsString = 'False') then
Continue;

if (GridView1.Columns[i].ColumnType = ctDate) and
(GridView1.Cell[i,j].AsString = '12/30/1899') then
Continue;

HasEdit := true;
Break;
end;
{
end//StrToInt( TV.CVTableCellArray[i,j,1]) > 0, i.e. infor from previous cell edit
else //non-numeric, date cell
begin
if (GridView1.Columns[i].ColumnType = ctNone) or
(GridView1.Columns[i].ColumnType = ctString) then
if GridView1.Cell[i,j].AsString <>
TV.CVTableCellArray[i,j,0] then
begin
HasEdit := true;
Exit;
end
else
if (GridView1.Columns[i].ColumnType = ctBoolean) then
if GridView1.Cell[i,j].AsBoolean <> (StrToInt(TV.CVTableCellArray[i,j,0])=1) then
begin
HasEdit := true;
Exit;
end;
}
end;//for j
if HasEdit then Break;

end; //for i

Result := HasEdit;

end;

procedure TfrmCVTable.SaveUserEdits;
//local function, return the ID used to store new/updated data
function SaveUpdateGridChanges(Action, Value : string;
RecID, RowID, ColID : integer): Integer;
begin
with ModData.dsql_AnyUse do
begin
//note: that the table can only be user edited for its cell data during the
//session it was created; once the session is closed the cell data cannot
//be changed; I intend to allow copying the entire table over to a new session
//from the session history grid but that is all
//An Update thus means that the user already added data to the cell, but went
//in to the table again and changed the data during the same session.

//The user once in a cell can change data any number of times, but the data
//saved is only that which exists in the cells at close of the table

if Action = 'UPDATERECORD' then
begin
SQL.Clear;
SQL.Add('UPDATE CV_TABLE_SESSIONS ');
SQL.Add('SET CV_COL_ROW_VALUE = :NewValue ' );
SQL.Add('WHERE CV_TABLE_SES_ID = :ID');

Prepare;
ParamByName('NewValue').asString := Value;
ParamByName('ID').asInteger := RecID;

ExecSQL;
// moddata.IB_Transaction1.Commit; USE UPDATERECORD INSTEAD; commit, doesn't
//cb: 10/18/05 This is true, do not change! (Why?)
UpdateRecord;
end;//Update

if Action = 'ADDRECORD' then
begin

RecID := cvDataCollection.GetGenID('CV_TABLE_SESSIONS');

SQL.Clear;
SQL.Add('INSERT INTO CV_TABLE_SESSIONS ');
//note trigger for PK (CV_TABLE_SES_ID), but need to know for grid array
SQL.Add('(CV_TABLE_SES_ID, CV_TABLE_ID , CV_COLUMN_ID, CV_ID, SES_ID, ' );
SQL.Add('CV_COL_ROW_VALUE ) ');
SQL.Add('VALUES ');
SQL.Add('(:tableSesID, :tableid, :ColID, :cvID, :SesID, ');
SQL.Add(' :NewValue )');

Prepare;

ParamByName('tableSesID').AsInteger := RecID;
ParamByName('tableid').AsInteger := tv.CVTableID;
ParamByName('ColID').AsInteger := ColID;
ParambyName('cvID').AsInteger := TV.CVTableRowCVID[RowID];
ParamByName('SesID').AsInteger := TV.SessionID;
ParamByName('NewValue').asString := Value;

ExecSQL;

ModData.IB_Transaction1.Commit;
end;//Add record

end; //ModData.dsql_AnyUse

Result := RecID;

end;

var
i, j, NewRecID :integer;
UpdateRecord : boolean;
AddRecord : boolean;
Msg : string;

begin
// we know that at least one cell was modified to call this routine

//if in old session display mode, change global var and exit;
//no changes to be made and none saved

if Utility.CurrentSession > 0 then
begin
TV.CVTableCellEdits := false;
Exit;
end;

//call message dlg to confirm saving of changes
Msg := 'Save Changes or Input to Table?';

if MessageDlg(Msg, mtConfirmation , [mbOK, mbCancel], 0) = mrOk then
begin

if not Assigned(SaveTableData) then
SaveTableData := TSaveTableData.Create(self);

SaveTableData.show;

Application.ProcessMessages;

//columns to rows
// TColumnType = (ctAutoInc, ctNone, ctGraphic, ctBoolean, ctDate,
// ctFloat, ctInteger, ctString, ctLookup, ctVirtual);

//Save Boolean as 'True'/'False'

for i:= 0 to GridView1.Columns.Count-1 do
begin

if i = 0 then Continue; //skipping the first, column which is not editable
//because it is the child nodes of the tree, nothing to input by user

for j:= 0 to GridView1.RowCount-1 do
begin
UpdateRecord := false;
AddRecord := false;

if GridView1.Cell[i,j].AsString <>
TV.CVTableCellArray[i,j,0] then
begin
//eliminate saving dates of '12/30/1899' or False for boolean type
//cb: well if user edits a true and makes it false, then catch that
if (GridView1.Columns[i].ColumnType = ctBoolean) and
(GridView1.Cell[i,j].AsString = 'False') and
(TV.CVTableCellArray[i,j,0] = '') then
Continue;

if (GridView1.Columns[i].ColumnType = ctDate) and
(GridView1.Cell[i,j].AsString = '12/30/1899') then
Continue;

//in 3rd dime element the cv_table_ses_id is stored, if blank not an update,
//but an insert of new value for cell in user's table
if TV.CVTableCellArray[i,j,1] <> '' then
UpdateRecord := True
else
AddRecord := True;

//update the record here, see local routine

end; //modifications to the cell

if AddRecord then
begin
//add to cell array
//the value
TV.CVTableCellArray[i,j,0] := GridView1.Cell[i,j].AsString;

//could get the column id this way too:
//:= TableColList[i];

TV.CVTableColID2Edit := StrToInt(Copy(GridView1.Columns[i].Footer.Caption, 1,
POS('|',GridView1.Columns[i].Footer.Caption)-1));

NewRecID := SaveUpdateGridChanges('ADDRECORD', TV.CVTableCellArray[i,j,0],
0, j, TV.CVTableColID2Edit );

//the cell info id
TV.CVTableCellArray[i,j,1] := IntToStrZeroPad(NewRecID, 10);
end;//AddRecord

if UpdateRecord then
begin
//change the cell array's value -- this is probably not necessary during Close!
TV.CVTableCellArray[i,j,0] := GridView1.Cell[i,j].AsString;
//no need to change cell info record id
//Now update the record
SaveUpdateGridChanges('UPDATERECORD', TV.CVTableCellArray[i,j,0],
StrToInt(TV.CVTableCellArray[i,j,1]), j, 0);
end;//UpdateRecord



end; //for i = 0

end;//for j:=0

SaveTableData.Close;

//cb: 5/3/07 record this in session_actions;
//to play back session
StoreSesAction('TABLECHK',tv.CVTableID);

end; //MessageDlg
end;


procedure TfrmCVTable.GridView1ColumnResize(Sender: TObject;
ACol: Integer);
var
i: integer;

begin
// use this to make changes in Col width; store in db for this Table-Column
//first, force a repaint of the grid, to show the new col width
//Hold off letting this fire until after form show, otherwise it resets the
//col width

if TV.EditTreeTable and TV.CVTableShow then
begin
with GridView1 do
begin
for i:= ACol to Columns.Count-1 do
begin
RefreshColumn(Columns[i]);
end;
end;
//Save changes to database
with ModData.dsql_AnyUse do
begin
SQL.Clear;
SQL.Add('UPDATE CV_TABLE_Columns ');
SQL.Add('SET TABLE_Col_width = ' + IntToStr(GridView1.Columns[ACol].Width ));
SQL.Add('WHERE CV_TABLE_ID = ' + IntToStr(TV.CVTableID) );
SQL.Add('AND TABLE_COL_ORDER = ' + IntToStr(ACol+1) );
ExecSQL;
//Moddata.IB_Transaction1.Commit
UpdateRecord;
end;
end;
end;

//stop any table resizing unless in edit mode or initial form show
procedure TfrmCVTable.FormCanResize(Sender: TObject; var NewWidth,
NewHeight: Integer; var Resize: Boolean);
begin
if ShowTableForm or TV.EditTreeTable then
Resize := true
else
Resize := false;

end;

procedure TfrmCVTable.GridView1CellFormating(Sender: TObject; ACol,
ARow: Integer; var TextColor: TColor; var FontStyle: TFontStyles;
CellState: TCellState);
begin
//if GridView1.Cell[ACol, ARow].ActualFontColor <>
// CFont.Color then

//somehow the Column.font.color property actually changes by the time
//this event is fired--wierd!
//I'm using array to store and retrieve colors instead (ColFontColor)

exit;

if (GridView1.Columns[Acol] <> nil) then
begin

TextColor := StringToColor(ColFontColor[ACol]); // GridView1.Columns[ACol].Font.Color;
FontStyle := [];
if Pos('B', TV.CVTableHdrFontStyle) > 0 then
FontStyle := FontStyle + [fsBold];
if Pos('U', TV.CVTableHdrFontStyle) > 0 then
FontStyle := FontStyle + [fsUnderline];
if Pos('I', TV.CVTableHdrFontStyle) > 0 then
FontStyle := FontStyle + [fsItalic];
end;

{ from demo, example of how to use
if (ACol = 5) then
begin
if (GridView1.Cell[5, ARow].AsInteger < 200) then TextColor := clRed;
if (GridView1.Cell[5, ARow].AsInteger > 1800) then TextColor := clBlue;
end;
}
end;


procedure TfrmCVTable.tbDeleteColClick(Sender: TObject);
var
Col2Delete : integer;
Col2DeleteID : string;

begin
//do not allow deletion of first column (which normally is associated with
//the folder's children
Col2Delete := GridView1.SelectedColumn;


if Col2Delete > 0 then //first column is column[0]
if MessageDlg('Deleting this column will eliminate all history file data' +CR +
'associated with this column for all patients in all sessions.' + CR +
'Do you wish to continue?' ,
mtWarning, [mbOK, mbCancel], 0) = mrOK then
begin
//now from grid itself
//these next two lines suggested by Berg himself and did not correct
//the deletion problem of the last column: causing "listindex beyond bounds (#)"

//GridView1.SelectedColumn := GridView1.SelectedColumn - 1;

Col2DeleteID := Copy(GridView1.Columns[Col2Delete].Footer.Caption,1,
Pos('|',GridView1.Columns[Col2Delete].Footer.Caption)-1);

GridView1.Columns.Delete(Col2Delete);
//remove the font.color from the StringList
ColFontColor.Delete(Col2Delete);

//remove it from the table
//note: there is a cascade delete on the associated data
with ModData.dsql_AnyUse do
begin
SQL.Clear;
SQL.Add('DELETE FROM CV_TABLE_Columns');
SQL.Add('WHERE CV_COLUMN_ID = ' + Col2DeleteID);
//GridView1.Columns[GridView1.SelectedColumn].Footer.caption );
ExecSQL;
ModData.IB_Transaction1.commit;
end;

end
else
Showmessage('You cannot delete the first column in the table since it is the folder''s tree children.');

end;

//the next two events Click or select cell will output the Col Hdr +
//Row caption as a Signal output if this is on.
//CB: looks like these are pretty similar except that CellClick actually
//activates the cell editor, QED use the Cell click event not SelectCell
{
procedure TfrmCVTable.GridView1SelectCell(Sender: TObject; ACol,
ARow: Integer);
begin
//showmessage('select cell');
//limit this to session mode for user
if TV.PatientID > 0 then
begin
TableCellSignalOut(ARow, ACol);

end;
end;
}

procedure TfrmCVTable.GridView1CellClick(Sender: TObject; ACol,
ARow: Integer);
begin
//right now using the same routine as SelectCell
GridView1SelectCell(Self, ACol, ARow);

end;

//moving this to Signal Out, need procedure for MainForm, too
{
Procedure TfrmCVTable.TableCellSignalOut(ARow, ACol: integer);
begin
if MLDefSignalOutput = 1 then
begin
//get the Signal output type from footer caption
//set global var
//TV.CVTableColFilterType :=
//make new routine different from Text2Speech which is mostly a series of
//queries


end;
end;
}

procedure TfrmCVTable.GridView1MouseMove(Sender: TObject;
Shift: TShiftState; X, Y: Integer);
var
RowNum ,
ColNum : integer;
Col : TNxCustomColumn;
begin
if TNextGrid(Sender).Name = 'GridView1' then
with GridView1 do
begin
RowNum := GetRowAtPos(x,y);
Col := GetColumnAtPos(point(x,y));

if Col <> nil then
begin
ColNum := GetColumnAtPos(point(x,y)).VisibleIndex;

//limit hints to columns and rows that actually exist and the text doesn't fit
//the cell
if (ColNum > -1) and (RowNum > -1) then
if RowExist(RowNum) and not IsTextFit(ColNum,RowNum) then
//don't bother with hints if the cell has wordwrap
if Col.WrapKind <> wkWordWrap then
Cell[ColNum,RowNum].Hint := Cell[ColNum,RowNum].AsString
else
Cell[ColNum,RowNum].Hint := '';

end;

end;
end;

//allow using arrow keys to move around grid
//Turns out this is built in when table is used for display, not for edit though
//Do not assign this event (every key move is doubled!)
procedure TfrmCVTable.GridView1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (Key in [VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN]) then
with GridView1 do
begin
if Key in [VK_DOWN] then
MoveSelectionDown(shift);
if Key in [VK_UP] then
MoveSelectionUp(shift);

if Key in [VK_Right] then
MoveSelectionRight;

if Key in [VK_LEFT] then
MoveSelectionLeft;

end;
end;


procedure TfrmCVTable.tbVernierClick(Sender: TObject);
begin
if frmVernierScale.Visible then
begin
frmVernierScale.Hide;
tbVernier.Down := false;
end
else
begin
//cb: below is really on for testing of the Scan Correction scale
//not used in the table; which uses all the regular scales -- RESET NOW

//only one type of scale for this (corrections count) use; make other disappear
frmVernierScale.rgScaleType.Visible := true; //false;
//frmVernierScale.SetUpVernierScale('Log 0-10');
frmVernierScale.SetUpVernierScale('LogScale');
frmVernierScale.Show;
tbVernier.Down := true;
end;
end;


function TfrmCVTable.GetVAlignment : TVerticalAlignment;
var
ColVAlign : TVerticalAlignment;

begin
//new VertAlignment property names
if TV.CVTableColVAlign = 'TOP' then
ColVAlign := TVerticalAlignment(taAlignTop) //vaTop
else
if TV.CVTableColVAlign = 'MIDDLE' then
ColVAlign := TVerticalAlignment(taVerticalCenter) //vaMiddle
else
if TV.CVTableColVAlign = 'BOTTOM' then
ColVAlign := TVerticalAlignment(taAlignBottom);//vaBottom

Result := ColVAlign;
end;


function TfrmCVTable.GetAlignment: TAlignment;
var
ColAlign : TAlignment;

begin
if TV.CVTableColAlign = 'LEFT' then
ColAlign := taLeftJustify
else
if TV.CVTableColAlign = 'CENTER' then
ColAlign := taCenter
else
if TV.CVTableColAlign = 'RIGHT' then
ColAlign := taRightJustify;

Result := ColAlign;

end;

procedure TfrmCVTable.tbTextAlignLeftClick(Sender: TObject);
begin
//this group of Text Alignment buttons; shows the status of the selected
//column;
end;

//below are default settings for the different types of columns, not
//saved in any table (at this point)
procedure TfrmCVTable.SetColDefaults(ColClass : TNxColumnClass; ACol: integer);
var
ColDatePicker : TNxDatePicker;

begin
//from SetProps:
{
if TV.EditTreeTable then
GridView1.Columns[Col].Options :=
[coCanClick, coEditing, coCanInput, coSearchColumn]
else
GridView1.Columns[Col].Options :=
[coCanClick, coEditing, coCanInput, coFixedSize, coSearchColumn];
}
with GridView1 do
begin
if ColClass = TNxDateColumn then
with TNxDateColumn(Columns[ACol]) do
begin

Options := Options + [coEditing, coEditorAutoSelect , coShowTextFitHint];
//EmptyCaption := ''; cb: 9/05/07 for some reason Delphi doesn't like this; get Assembler debug window
//public var for later comparison; default values not used at this time
DefDate := DateToStr(Now);
DefaultValue := DefDate;
//if goUseDefaultValues = true, then cell will be filled with default
HideWhenEmpty := true;
end
else
if ColClass = TNxIncrementColumn then
with TNxIncrementColumn(Columns[ACol]) do
begin
Options := Options + [coEditing, coCanInput];
Options := Options - [coCanInput, coCanSort, coPublicUsing];
end
else
if ColClass = TNxCheckBoxColumn then
with TNxCheckBoxColumn(Columns[ACol]) do
begin
Options := Options + [coEditing];
Options := Options - [coCanInput];
end
else
if ColClass = TNxImageColumn then
with TNxImageColumn(Columns[ACol]) do
begin
Images := imlGrid;
//right now there is little support for editing an image column
//would need to add more images to imlGrid and have some way of setting
//image logic; below would keep the form from having errors
DefaultValue := '0';
Options := Options - [coCanInput, coPublicUsing];
end
else
if ColClass = TNxNumberColumn then
with TNxNumberColumn(Columns[ACol]) do
begin
//Mask was wrong and causing problem with not showing a zero, but a blank
//FormatMask := '###,###,###,###,###';
//FormatMask := '[#][#][#],[#][#][#],[#][#][#],[#][#][#],[#][#]#' ;

//below format is best I can do; format mask treats blanks as zeros;
//no easy way around this. I could change all "numeric" cols to string col for
//display purposes, but wondering what the repercussions would be? (hard to graph,
//harder formating issues?, not to mention more coding)

FormatMask := '###,###,###,###,###;;0';
//Berg recommended below, which did not help at all, plus I don't want 2 decimal
//places
//FormatMask := '#,##0.00';
Options := Options + [coEditing, coEditorAutoSelect];
//cb: i want a blank cell when no user input and a 0 to show if user
//selected a 0 ; below do not work
//increment := 1;
//DefaultValue:= '0';// keep null or blank; cb: doesn't make any difference
//Min := 0;
//Precision := 0;
HideWhenEmpty := false;
end
else
if ColClass = TNxTextColumn then
with TNxTextColumn(Columns[ACol]) do
begin
//InputCaption := <consider adding to the ColTitle dlg>
//cb: looks like MouseMove of Grid is not enough to end hints for full description
//wordwrap cells; do not have coShowTextFitHint to eliminate obnoxious
//hint for a full text cell

if WrapKind = wkWordWrap then
Options := Options + [coEditing, coEditorAutoSelect]
else
Options := Options + [coEditing, coEditorAutoSelect, coShowTextFitHint];

end
else
if ColClass = TNxComboBoxColumn then
with TNxComboBoxColumn(Columns[ACol]) do
begin
//make the first item in the list the default
DefaultValue := TNxComboBoxColumn(GridView1.Columns[ACol]).Items[0];
Options := [coEditing];
Style := cbsDropDownList;
OnSelect := NxComboBoxColumn1Select;
end
else
if ColClass = TNxProgressColumn then
with TNxProgressColumn(Columns[ACol]) do
begin
HideWhenEmpty := true;
Max := 100;
Options := Options - [coCanInput, coPublicUsing];
Options := Options + [coEditing];
ProgressStyle := psSolid;
end;


end;//Gridview1

end;

procedure TfrmCVTable.GridView1CellColoring(Sender: TObject; ACol,
ARow: Integer; var CellColor, GridColor: TColor; CellState: TCellState);
begin
//columns.color is set from the table; can be adjusted by clicking on the
//col header and accessing the col props editor
if GridView1.Columns[ACol] <> nil then
begin
CellColor := GridView1.Columns[Acol].Color;

//for selected cells give a different color
//This is weird, it does the exact opposite: unselected cells are light blue
if (csSelected in CellState) then
CellColor := clSkyBlue;

end;
{
if CellColor = clWhite then
CellColor := clSkyblue
else
CellColor := cWhite;
}
{
with GridView1 do
begin
if (ACol = SelectedColumn) and (ARow = SelectedRow) then
if CellColor = clWhite then
Cell[ACol, ARow].Color := clSkyBlue
else
Cell[ACol, ARow].Color := clWhite;
end;
}
//I got the next line from NextGrid demo, but it just doesn't work at all

///GridView1.Canvas.Font.Color := clRed;
//GridView1.Cell[ACol, ARow].ActualFontColor := Columns[ACol].Font.Color ;
end;

procedure TfrmCVTable.seHeaderHeightChange(Sender: TObject);
begin
Gridview1.HeaderSize := Trunc(seHeaderHeight.value);
end;

procedure TfrmCVTable.mxCaptionBarButtons1Buttons1Click(Sender: TObject);
begin
frmCVTable.Close;
end;


//this fires even during set up, so everything changes, even on loading
procedure TfrmCVTable.GridView1Change(Sender: TObject; ACol,
ARow: Integer);
begin
//any cell changes should trigger the potential to save those changes
//The Memo field is checked and saved independently

if (ACol <= GridView1.Columns.Count) and
(ARow <= GridView1.RowCount) then
begin
TV.CVTableCellEdits := true;
//mxCaptionSave.visible := true;
//cb: see below, no longer using Save button all changes detected and
//trapped in Close caption
//mxCaptionBarbuttons1.Buttons[0].Visible := true;

end;

end;

procedure TfrmCVTable.mxCaptionBarButtons1Buttons0Click(Sender: TObject);
begin
if TV.CVTableCellEdits then
begin
//go through each row and col
end;
end;

procedure TfrmCVTable.GridView1AfterEdit(Sender: TObject; ACol,
ARow: Integer; Value: WideString);
begin
//any cell changes should trigger the potential to save those changes
//The Memo field is checked and saved independently. Not a user edit field,
//for display only of directions, etc for table


//this event works fine for cell that have their own auto-editor functioning
//Not so with numerical cells that use the Vernier;
if (ACol <= GridView1.Columns.Count) and
(ARow <= GridView1.RowCount) then
begin
TV.CVTableCellEdits := true;
//mxCaptionSave.visible := true;
//no longer Save button; all trapped in Close, because numerical cells
//are not using self editors, thus OnAfterEdit does not fire and thus
//TV.CVTableCellEdits does not reliably change for all edits

//mxCaptionBarbuttons1.Buttons[0].Visible := true;

end;
end;

procedure TfrmCVTable.GridView1SelectCell(Sender: TObject; ACol,
ARow: Integer);
var
AFooter, AScale: string;

begin
if (TV.CVTableShow) and not (TV.EditTreeTable)
and (TV.PatientID > 0) then
begin
tbVernier.Enabled := true;
//start by putting out the signal, async ; in SignalOutput
TableCellSignalOut(GridView1,ARow, ACol);
//check col type if numeric, auto show vernier
//May add ability to auto set the scale in the vernier --DID!
//if (GridView1.Columns[ACol].ColumnType = ctInteger) or
//(GridView1.Columns[ACol].ColumnType = ctFloat) then

//using string columns for numbers ; anything other than null after
//the # indicates a scale type : -1 = no scale or vernier popup
//0= user to select scale; 1= log, etc

if (GridView1.Columns[ACol].ColumnType = ctString) and
(Copy(GridView1.Columns[ACol].Footer.Caption,
Pos('#',GridView1.Columns[ACol].Footer.Caption)+1,2) <> '-1') then
begin
tbVernier.Enabled := true;
//the grid cell is set into editor mode which puts the Vernier behind
//the table form (even though it is stay on top!)
//Below stops this
//Do I have option in Col header dlg to set a column to use the vernier
//as the editor? Not now

//[coEditing,coCanInput, coCanClick];
GridView1.Columns[ACol].Options :=
GridView1.Columns[ACol].Options - [coEditing]; //this is the important one
// TNxNumberColumn(GridView1.Columns[ACol]).SpinButtons := false;

//to remove to allow use of vernier

//when auto selecting scale, make visible = false

AFooter := GridView1.Columns[ACol].Footer.Caption;
TV.CVTableColScale := StrToInt(Copy(AFooter, Pos('#',AFooter)+1, MaxInt));

if TV.CVTableColScale = 0 then
frmVernierScale.rgScaleType.Visible := true
else
frmVernierScale.rgScaleType.Visible := false;

//for auto scale select: set the type of scale
case
TV.CVTableColScale of

1:
AScale := 'LogScale';
2:
AScale := 'Percent';
3:
AScale := 'VAS';
4:
AScale := '-/+ 100';
5:
AScale := 'Log 0-10';
6:
AScale := 'Affinity Test Threshold';
7:
AScale := 'RDA'; //cb: 10/2/06 in future
8:
AScale := 'Centuries';
end; //case

frmVernierScale.SetUpVernierScale(AScale);

//store cell location to global var
TV.CVTableRowEdit := ARow;
TV.CVTableColEdit := ACol;

//cb 8/26/07 using JvCaptionButton now, instead and it is alwaws visible
//frmVernierScale.CaptionBtns.Buttons[0].Visible := true;

frmVernierScale.Show;
frmVernierScale.BringToFront;
frmVernierScale.SetFocus;
tbVernier.Down := true;
end //column type=int
else
begin
//not a numeric col, so do not show vernier
frmVernierScale.Hide;
tbVernier.Enabled := false;
tbVernier.Down := false;
end;
end; //patient mode

end;

procedure TfrmCVTable.capBtnCloseClick(Sender: TObject);
begin
frmCVTable.Close;

end;

procedure TfrmCVTable.GridView1BeforeEdit(Sender: TObject; ACol,
ARow: Integer; var Accept: Boolean);
begin
//here to avoid user editing a display only table (from a previous session)
//ReadOnly of GridView/NextGrid setting doesn't work
if Utility.CurrentSession > 0 then
Accept := false
else
//do not allow adding data to a table if in sysmaint mode (i.e. no patient to
//apply values to; use Test Patient instead if for testing

//TreeViewMode is either CLIENTS or SYSMAINT
if TV.TreeViewMode = 'SYSMAINT' then
Accept := false
else
//stop editing of 1st or col[0]
if ACol = 0 then
Accept := False
else
if ACol > 0 then
Accept := true;

end;

procedure TfrmCVTable.capBtnCloneTableClick(Sender: TObject);
var
Data : PNodeData;

begin
//move current data from old session to current session
Data := TV.CurrentCVTree.GetNodeData(TV.CurrentCVTree.FocusedNode);
//will be a datapump to move/insert all cells
with ModData.dsql_AnyUse do
begin
SQL.Clear;
SQL.Add('INSERT INTO CV_TABLE_Sessions ');
SQL.Add('(CV_TABLE_ID , CV_COLUMN_ID, CV_COL_ROW_VALUE, CV_ID, SES_ID )');
SQL.Add('SELECT CV_TABLE_ID , CV_COLUMN_ID, CV_COL_ROW_VALUE, CV_ID, ');
SQL.Add(IntToStr(Utility.CurrentSession) +' as Ses_id ');
SQL.Add('FROM cv_table_sessions WHERE cv_table_id = :cvtableid ' );
SQL.Add('AND ses_id = :sesid');
Prepare;
ParamByName('cvtableid').asInteger := TV.CVTableID;
//at this point TV.SessionID = the session history session id; the current
//session is in this var...
// ParamByName('sessionid').AsInteger := Utility.CurrentSession;
ParamByName('sesid').AsInteger := TV.SessionID; //older session at this point
ExecSQL;
ModData.IB_Transaction1.Commit;
end;

//save as a session action
StoreSesAction('TABLECLONE', Data.Id);
ShowMessage('Data from previous table cloned successfully.' + CR +
'Closing table...');
//now,close the form
frmCVTable.Close;

end;

procedure TfrmCVTable.NxComboBoxColumn1Select(Sender: TObject);
begin
with GridView1 do
begin
Cell[SelectedColumn, SelectedRow].AsString :=
TNxComboBoxColumn(Sender).Editor.Text;
end;
end;


procedure TfrmCVTable.ib_error(Sender: TObject; const ERRCODE: Integer;
ErrorMessage, ErrorCodes: TStringList; const SQLCODE: Integer;
SQLMessage, SQL: TStringList; var RaiseException: Boolean);
begin
moddata.IB_OnError(Sender, ERRCODE,ErrorMessage, ErrorCodes,SQLCODE,
SQLMessage, SQL, RaiseException);
end;

//foot pedal routines to fire mainform popup macros
procedure TfrmCVTable.popmnuFPHiddenPopup(Sender: TObject);
begin
abort;
end;

procedure TfrmCVTable.RightFootPedal1Click(Sender: TObject);
begin
Utility.FPOnForm := frmCVTable.Name;
Utility.FPFormsActiveControl := frmCVTable.ActiveControl;
MainForm.RightFootPedal1.Click;
end;

procedure TfrmCVTable.LeftFootPedal1Click(Sender: TObject);
begin
//calls Mainform popup action
Utility.FPOnForm := frmCVTable.Name;
Utility.FPFormsActiveControl := frmCVTable.ActiveControl;
MainForm.LeftFootPedal1.Click;
end;

procedure TfrmCVTable.MiddleFootPedal1Click(Sender: TObject);
begin
Utility.FPOnForm := frmCVTable.Name;
Utility.FPFormsActiveControl := frmCVTable.ActiveControl;
MainForm.MiddleFootPedal1.Click;
end;

initialization

RegisterClasses( [TNxButtonColumn, TNxGraphicColumn, TNxCheckBoxColumn,
TNxDateColumn, TNxHTMLColumn, TNxImageColumn, TNxIncrementColumn,
TNxComboboxColumn, TNxNumberColumn, TNxProgressColumn, TNxRateColumn,
TNxTextColumn, TNxListColumn]);

end.


#6 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 07 September 2007 - 12:33 AM

Hello Chuck,

Can you please send me one smaller sample code and add dfm file into zip archive please. You may use next example, and extend it with your code:

Attached File  nxcombo.zip   3.97KB   55 downloads

Best regards
boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#7 BelangerC

BelangerC

    Senior Member

  • Members
  • PipPip
  • 221 posts
  • Location:Richmond, CA USA
  • Interests:Alternative medicine, programming for

Posted 07 September 2007 - 01:07 AM

Hello, Boki

Sure, but I'm not sure what you want. I can send you the full unit and its DFM, but anything less, may not get at the problem.

Like I said, if I create a small app or even a separate form from uCVTable, everything works as expected. So, if I break out the basic code and put that smaller unit into the unit1.pas, it will prove nothing and it will probably work just fine.

Let me know in more detail what you want.

Thanks,

Chuck

#8 BelangerC

BelangerC

    Senior Member

  • Members
  • PipPip
  • 221 posts
  • Location:Richmond, CA USA
  • Interests:Alternative medicine, programming for

Posted 07 September 2007 - 08:08 AM

Hello, Boki:

Found the problem. It was an OnBeforeEdit routine. I forgot that I restricted editing in certain program modes and I had no idea that the combo box would not display if it was in a non-editing mode.

Now I know.

Thanks for letting me work it out in your forum.

Chuck Belanger

#9 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 07 September 2007 - 03:42 PM

Hello Chuck,

I hope that now is all fine smile.gif

Best regards
boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users