ICsv interface
ICsv interface is used to work with csv
files.
Csv files are used to store tables. It is text where rows are separated by
new lines, cells by commas, values containing new lines, commas or double
quotes are enclosed in double quotes, double quotes are doubled, spaces around
commas and new lines are ignored. Example:
value1,value2, value3
11,22,33
"value, with, commas","value with ""quotes""","multiline
value"
,,
,rows with empty values,
,,
The CSV file format is supported by many programs including Microsoft Excel,
and therefore can be used to exchange data between them. However it have become
somewhat of a legacy format. The mainsteam format now is xml,
which is more powerful but adds much overhead (slower parsing/composing, requires
more space in file and in memory). To save tables, CSV format often is better
and easier to use.
You can find more information about CSV on the Internet.
Csv files also can be manipulated using Database
class, but it is slower.
Added in QM 2.3.0.
Use function CreateCsv to create a csv object. To
work with it, use ICsv interface. Example:
str s ss
ICsv v=CreateCsv
v.FromFile("$my qm$\test.csv")
int nr=v.RowCount
int nc=v.ColumnCount
int r c
for r 0 nr
out "--- row %i ---" r
for c 0 nc
s=v.Cell(r c)
out s
s.trim
v.Cell(r c)=s
v.ToString(ss)
out ss
Functions
interface# ICsv :IUnknown
[p]Separator($sep)
FromString($s)
ToString(str*so)
FromFile($file)
ToFile($file [append])
FromQmGrid(hwnd [flags])
ToQmGrid(hwnd [flags])
Clear()
[g]#ColumnCount()
[g]#RowCount()
[g]$Cell(row col)
[p]Cell(row col $value)
RemoveRow(row)
#AddRowMS(row ncells $cells)
#AddRowLA(row ncells lpstr*cells)
#AddRowSA(row ncells str*cells)
{3426CF3C-F7C1-4322-A292-463DB8729B54}
dll "qm.exe" ICsv'CreateCsv
CreateCsv - creates a csv object and returns ICsv
interface pointer. Since it is a COM object, it is destroyed automatically when
goes out of scope.
Separator - changes default separator that is used
when parsing and composing csv. Example: v.Separator=";".
Default separator on most computers is comma, but somewhere it is semicolon.
It can be changed in Control Panel -> Regional and Language Options ->
Customize... -> List Separator.
FromString - parses a csv string and creates table
in memory. The table is managed by the csv object.
Error if the csv string contains errors or uses different separator.
ToString - composes a csv string from the table.
FromFile - parses a csv file and creates table in
memory.
Error if the csv file contains errors or uses different separator.
QM 2.3.0. Can use syntax ":resourceid filepath" to add the file to
exe resources.
ToFile - saves the table to a csv file. flags:
1 - append.
FromQmGrid - creates table from a QM_Grid
control. flags: 1 - except first column; 2 - trim spaces.
Note: The control is not available in exe.
About QM_Grid control
This control is based on SysListView32 control. You can use its messages, notifications
and styles. They are documented in the MSDN Library.
In addition to SysListView32 control functionality, QM_Grid control allows user to edit all
or some cells, and can also show other controls, such as combo box, check box and button.
By default, this control can be used to enter text, like with edit control but where each
line is divided into columns. It also can be used to enter values of multiple properties,
instead of dialog with multiple controls, similarly as in many programming IDEs.
By default, to edit cells, is displayed temporary single-line edit control. You can use
LVM_QG_SETCELLTYPE and/or LVM_QG_SETCOLUMNTYPE to set other control types and styles.
These control types/styles are supported: single-line edit (default), multiline edit,
combo box (edit with drop-down list), sorted combo box, check box (sets item text to Yes
or empty), and none (read-only text). Also, a button can be displayed by the control.
A. Initializing
1. Create control of QM_Grid class (for example in dialog editor). Optionally use listview styles.
2. Optionally set listview extended styles, imagelists.
3. Optionally send LVM_QG_SETSTYLE.
4. Add columns (LVM_INSERTCOLUMN).
5. Optionally send LVM_QG_SETCOLUMNTYPE to set default cell control type for columns (initially it is QG_EDIT).
6. Add items and subitems. You can use listview messages (LVM_INSERTITEM, etc). Or use LVM_QG_SETALLCELLS to add all cells. Or use ICsv.ToQmGrid. You can add items and subitems in single call, or you can add items only, and later add subitems.
7. Optionally send LVM_QG_SETCELLTYPE to set control types of separate cells.
B. Receiving notifications.
You can optionally process LVN_ and LVN_QG_ notifications.
You must process LVN_QG_BUTTONCLICK for cells that have QG_BUTTONATRIGHT style. For example, show a dialog and set edit control text.
You must process LVN_QG_COMBOFILL for cells that have QG_COMBO type. Use CB_ADDSTRING to add combo box items. This message is sent each time before showing dropdown list.
You optionally can process LVN_QG_COMBOITEMCLICK for cells that have QG_COMBO type. If you don't process it, or process but return 0, combo box edit control text is set to selected item's text. This message allows you to override this behavior. You for example can show a dialog, set edit control text, and return 1.
Also you can process LVN_ENDLABELEDIT to validate user input, save/apply, etc.
C. Getting text from cells.
Use LVM_GETITEMTEXT to get text from each cell you need. Or, use LVM_QG_GETALLCELLS to get all cells. Or use ICsv.FromQmGrid.
D. Mouse and keyboard navigation.
Click cell to edit it.
Click-drag at right or left to select rows. Also, you can Ctrl+Click or Shift+Click.
Right click or use App key to show context menu.
In cell edit mode:
Use Tab, Shift+Tab or arrows to edit next, prev, below or above.
Use Enter to insert and edit new row.
Use standard edit control navigation and context menu.
Use Esc to deactivate cell edit mode.
Not in cell edit mode:
Use Spacebar to edit first editable cell of selected or first row.
Use Ctrl+A to select all, Delete to delete selected, Ctrl+Up/Down to move selected cell.
//////////////////////////////////////////////////
Definitions
Styles (use with LVM_QG_SETSTYLE)
def QG_NOEDITFIRSTCOLUMN 1 ;;does not allow user to edit cells in first column.
def QG_NOAUTOADD 2 ;;does not allow user to add, delete, insert and move rows.
By default, all cells are editable, and user can easily add, delete and move rows.
And you can use list view control styles.
Cell control flags (use with LVM_QG_SETCELLTYPE and LVM_QG_SETCOLUMNTYPE)
control type
def QG_EDIT 1
def QG_COMBO 2
def QG_CHECK 3
def QG_NONE 7 ;;read-only text
def QG_CONTROLTYPEMASK 7 ;;not used
control style
def QG_EDIT_MULTILINE 8 ;;use with QG_EDIT
def QG_COMBO_SORT 8 ;;use with QG_COMBO
def QG_BUTTONATRIGHT 16 ;;use with any type
example: QG_EDIT|QG_EDIT_MULTILINE|QG_BUTTONATRIGHT ;;multiline edit control with button
LVM_QG_SETALLCELLS flags
def QG_SET_FIRST 1 ;;set only first column
def QG_SET_NOFIRST 2 ;;set all except first column
LVM_QG_GETALLCELLS flags
def QG_GET_NOFIRST 1 ;;get all except first column
def QG_GET_TRIM 2 ;;trim spaces from cell values
Messages
def LVM_QG_FIRST (LVM_FIRST+240) ;;not used
def LVM_QG_SETSTYLE (LVM_QG_FIRST) ;;Sets grid style (defined above). wParam is styles, lParam is mask (can be used -1).
def LVM_QG_SETCELLTYPE (LVM_QG_FIRST+1) ;;Sets control flags of a single cell (defined above). wParam is item, lParam is column in low-order word and flags in high-order word (flags<<16|column).
def LVM_QG_SETCOLUMNTYPE (LVM_QG_FIRST+2) ;;Sets default control flags for all cells of specified column (defined above). wParam is column, lParam is flags.
def LVM_QG_SETALLCELLS (LVM_QG_FIRST+3) ;;Populates all cells from a str variable containing multistring. wParam is LVM_QG_SETALLCELLS flags (defined above), lParam is address of the str variable.
def LVM_QG_GETALLCELLS (LVM_QG_FIRST+4) ;;Gets all cells to a str variable as multistring. wParam is LVM_QG_GETALLCELLS flags (defined above), lParam is address of the str variable.
Notes
A multistring is array of strings where all strings are in same str variable, each string is terminated with null character. Multistrings can be stored in registry with REG_MULTI_SZ type.
Checkbox cell text is "Yes" if checked, empty if unchecked.
Notifications
def LVN_QG_FIRST (LVN_LAST) ;;not used
def LVN_QG_BUTTONCLICK (LVN_QG_FIRST) ;;Sent on button click. Do whatever you want and return 0.
def LVN_QG_COMBOFILL (LVN_QG_FIRST+1) ;;Sent on combobox dropdown. Fill the combo box and return 0.
def LVN_QG_COMBOITEMCLICK (LVN_QG_FIRST+2) ;;Sent on combobox item clicked. Return 0, or 1 to preserve edit control text.
def LVN_QG_CHANGE (LVN_QG_FIRST+3) ;;Sent on cell text changed. Return 0.
Address of variable of this type is sent with LVN_QG_ notifications as lParam.
Some members are used only with certain notifications.
type QM_NMLVDATA NMHDR'hdr hctrl hcb ctrltype item subitem cbindex $txt
hdr - notification code, grid control handle and id.
hctrl - edit control (not grid control).
hcb - combo box control.
ctrltype - cell flags from QM_GRID_ITEM_FLAGS.
item and subitem - specifies the cell.
cbindex - on LVN_QG_COMBOITEMCLICK it is index of selected combo box item.
txt - edit control text.
Also, the control extends these SysListView32 messages and notifications:
LVM_EDITLABEL ;;lParam specifies subitem.
LVN_BEGINLABELEDIT ;;LVITEM.iSubItem specifies subitem.
LVN_ENDLABELEDIT ;;LVITEM.iSubItem specifies subitem. Return 1 to leave old text.
ToQmGrid - populates a QM_Grid control. flags:
1 - only first column; 2 - except first column.
Clear - deletes all rows.
ColumnCount, RowCount -
gets the number of columns and rows in the table.
Cell - gets or sets cell value. See the above example.
Note that the returned value becomes invalid after calling a function that modifies
the table, and therefore you should assign it to a str variable, like in the
example.
RemoveRow - removes a row.
AddRowMS, AddRowLA, AddRowSA - add a row.
row - 0-based row index where the new row must be inserted. Use an invalid
index (e.g. -1) to add to the end.
ncells - number of cells to add. If the table is empty, it sets the
number of columns. Else it must not be more than the number of columns.
cells - cell values.
Each of these functions differs only by the format of values (cells).
With MS, cells must be a multistring, ie single buffer containing multiple
string separated by null character. With LA, cells must be address of
first variable in an array of lpstr variables. With SA - str variables. If cells
is omitted or 0, adds an empty row. You can use Cell
to set cell values.
Notes
ICsv functions are not thread-safe. Don't use a single
variable in multiple threads simultaneously. It can damage data. If needed to
use in multiple threads, use lock.