Latest work - version 0.18. Although not completely finished,
[object] Table is usable now.
Code:
;===oTable testing area=================================================================
Variable = ; column names are specified as first row
(
First name%A_Tab%Last name%A_Tab%Occupation%A_Tab%Notes
Jack%A_Tab%Gates%A_Tab%Driver%A_Tab%
Mark%A_Tab%Weber%A_Tab%Student%A_Tab%His father is a driver.
Jim%A_Tab%Tucker%A_Tab%Driver%A_Tab%
Jill%A_Tab%Lochte%A_Tab%Artist%A_Tab%Jack's sister.
Jessica%A_Tab%Hickman%A_Tab%Student%A_Tab%
Mary%A_Tab%Jones%A_Tab%Teacher%A_Tab%Her favorite song is "D r i v e r".
Lenny%A_Tab%Stark%A_Tab%Driver%A_Tab%
Jack%A_Tab%Black%A_Tab%Actor%A_Tab%His wife is artist.
Tony%A_Tab%Jackman%A_Tab%Surfer%A_Tab%
Jonny%A_Tab%Poor%A_Tab%Beggar%A_Tab%
Scott%A_Tab%Jenstan%A_Tab%Teacher%A_Tab%Lives in New York.
)
oTable := Table_ObjCreate(Variable) ; creates table object from variable
Variable = ; not longer needed
; create simple gui for testing
Gui 1: Add, ListView, x5 y5 w500 h300 grid, % oTable.HeaderToString("|") ; converts table's header (first row) to string.
Gui 1: Show, w510 h310 hide
;=== Field management ===
;MsgBox % oTable.3.2 ; get value from [3. row, 2. column]
;oTable.1.1 := "Bobby" ; set [1. row, 1. column] to "Bobby"
;=== Converting to numbers ===
;MsgBox % oTable.Row2Num("Jonny", "Poor", "Beggar") ; get number of row whose fields are: Jonny, Poor, Beggar. (Identification by fields)
;MsgBox % oTable.Col2Num("Occupation") ; get number of "Occupation" column
;MsgBox % oTable.Col2Num("First name|Notes") ; get numbers of "First name" and "Notes" columns
;=== ToString method ===
;MsgBox % oTable.ToString() ; convert whole table object to string
;MsgBox % oTable.3.ToString() ; convert 3. row object to string
;MsgBox % oTable.11.ToString("#") ; convert 11. row object to string but use custom delimiter
;MsgBox % oTable.HeaderToString() ; converts table's header (first row) to string
;=== MaxIndex (Count) ===
;MsgBox % oTable.MaxIndex() ; get total number of rows (in future maybe: oTable.Count)
;MsgBox % oTable.ColumnNames.MaxIndex() ; get total number of columns
;=== Row management ===
oTable.AddRow("Joe", "Newman", "Kiteboarder", "Freestyle & Wave") ; add row (to the bottom)
;oTable.InsertRow(2 ,"Mike", "Insertovich", "Actor") ; inserts new row number 2.
;oTable.ModifyRow(3 ,"Sergey", "Modifysky", "Actor") ; modify row number 3.
;oTable.ModifyRow(0 ,"Chris", "Allman", "Actor") ; modify all existing rows
;oTable.DeleteRow(2) ; delete 2. row
;oTable.DeleteRow() ; delete last row
;oTable.DeleteRow(0) ; delete all rows
;=== Searching ===
;MsgBox % oTable.Search("Occupation", "Driver").ToString() ; search Occupation column for containing string "driver"
;MsgBox % oTable.Search("Occupation|Notes", "Driver").ToString() ; search Occupation and Notes columns for containing string "driver"
;MsgBox % oTable.Search("", "Driver", "containing+").ToString() ; search whole table (all columns) for containing string "driver" but ignore withespaces
;MsgBox % oTable.Search("Last name", "^J.*an$", "RegEx").ToString() ; Search for all last names starting with "J" and ending with "an".
;MsgBox % oTable.Search("First name", "ny", "EndingWith").ToString() ; search first names ending with "ny"
;MsgBox % oTable.Search("Last name", "ja|bla", "StartingWith").ToString() ; search last names starting with "ja" or "bla"
;MsgBox % oTable.Search("", "Jack", "exactly").ToString() ; search whole table (all columns) for string "Jack" (not containing, but exactly)
;=== Multiple filters search ===
; step 1: search "Occupation" and "Notes" columns for containing "Driver" or "artist" strings. "|" is query delimiter.
; step 2: search that search result again: search "First name" column for containing "J" string
;oFound := oTable.Search("Occupation|Notes", "Driver|artist") ; store search results as object
;oFound2 := oFound.Search("First name", "J") ; search oFound (second search filter)
; or shorter: oFound2 := oTable.Search("Occupation|Notes", "Driver|artist").Search("First name", "J") ; etc. --> multiple filters
;MsgBox % oFound2.ToString() ; convert search results to string
;MsgBox % oFound2.2.ToString() ; convert 2. row from search results to string
;MsgBox % oFound2.1.3 ; get [1. row, 3. column] field from search results
;MsgBox % oFound2.MaxIndex() ; get number of found rows - from oFound2 (in future maybe: oFound2.Count)
;=== RegEx search === and LastFound property
; Search for all last names starting with "J" and ending with "an"
;oFound3 := oTable.Search("Last name", "^J.*an$", "RegEx") ; store search results as object
;MsgBox % oFound3.ToString() ; convert search results to string
;MsgBox % oFound3.LastFound ; each time after calling search method, row numbers of found rows are stored in LastFound key/property - read only.
;=== Massive StringReplace ===
;oTable.StringReplace("y", "X", ".", " :)") ; replaces "param1" with "param2", "param3" with "param4" (etc.) in all fields in table object.
;=== Interacting with files ===
;oTable := Table_ObjCreate(A_ScriptDir "\Table file.txt") ; creates table object from constructor file
;oTable.Save() converts table object to string and saves it to its constructor file. Use only if oTable is created from file.
;oTable.SaveAs(A_ScriptDir "\Table file.txt") ; converts table object to string and saves it to specified file.
;oTable.Open() ; opens table's constructor file in Notepad if it exists
;oTable.Reload() ; reads table's constructor file again and reconstructs table object if constructor file exists
;oTable.SaveAs(A_ScriptDir "\Table file.txt","|","#") ; converts table object to string and saves it to specified file but uses custom delimiters.
; When constructing table from such file, must specify custom delimiters --> oTable := Table_ObjCreate(A_ScriptDir "\Table file.txt","|","#")
;=== ToListView method ===
F1:: ; shows whole oTable in ListView
LV_Delete() ; empty ListView
oTable.ToListView()
Gui 1: Show
Return
F2:: ; finds all drivers and shows search results in ListView
LV_Delete() ; empty ListView
oTable.Search("Occupation", "driver").ToListView()
Gui 1: Show
Return
F3:: ; Do a RegEx search and show search results in ListView
LV_Delete() ; empty ListView
oFound := oTable.Search("Last name", "^J.*an$", "RegEx") ; Search for all last names starting with "J" and ending with "an".
oFound.ToListView()
Gui 1: Show
;MsgBox, 64, Numbers of found rows in latest search, % oFound.LastFound ; LastFound property
;MsgBox, 64, oFound to string, % oFound.ToString()
Return
F4:: ; search whole table (all columns) for containing string "new" and show search results in ListView
LV_Delete() ; empty ListView
oTable.Search("","New").ToListView() ; empty 1. parameter means: search through whole table (all columns)
;oTable.1.ToListView() ; adds 1. row from oTable to ListView
Gui 1: Show
return
/*
;=== oTable - ListView interaction ===
d::oTable.LVDelete() ; delete selected row
a::oTable.LVAdd("Mia","Addstan","Driver") ; add new row
e:: ; edit selected row
CurFields =
oCurFields := oTable.LVModify1() ; returns row's to modify fields. Must be called prior to oTable.LVModify2()
for k,v in oCurFields
CurFields .= v "|"
CurFields := RTrim(CurFields,"|")
if (CurFields = "") ; nothing selected
return
InputBox, NewRow,, Current Fields: %CurFields%,,,,,,,,%CurFields%
if ErrorLevel
return
oNewFields := SplitToObj(NewRow)
oTable.LVModify2(oNewFields) ; modifies row in ListView and oTable
return
*/
;===oTable Functions====================================================================
Table_Version() {
return 0.18
}
Table_ObjCreate(InputVariableOfFile, ColumnsDelimiter="`t", RowsDelimiter= "`n") {
static TableBase := Table_Base("HeaderToString StringReplace Search ToString ToListView NewFromScheme AddRow InsertRow ModifyRow DeleteRow Col2Num Row2Num Open Save SaveAs Reload Row2NumL LVSelInfo LVDelete LVAdd LVModify1 LVModify2", "Table_mTable_")
static RowBase := Table_Base("ToString ToListView", "Table_mRow_")
oTable := Object("base", Tablebase, "ColumnsDelimiter", ColumnsDelimiter, "RowsDelimiter", RowsDelimiter)
oColumnNames := Object()
IfExist, %InputVariableOfFile% ; construct table from file
{
oFile := FileOpen(InputVariableOfFile, "r `n", "UTF-8") ; hard coded or option...?
InputVariable := oFile.Read()
oFile.Close()
oTable.FilePath := InputVariableOfFile ; store constructor file's FilePath
}
else ; construct table from variable
InputVariable := InputVariableOfFile
Loop, parse, InputVariable, %RowsDelimiter%
{
CurRow := A_LoopField
if A_index = 1 ; column names are specified as first row
{
Loop, parse, CurRow, %ColumnsDelimiter%
{
oColumnNames.Insert(A_LoopField)
ColumnsCount++
}
oTable.ColumnNames := oColumnNames
continue
}
RowNum := A_index-1
%RowNum% := Object("base", RowBase, "table", oTable)
StringSplit, field, CurRow, %ColumnsDelimiter%
Loop, %ColumnsCount%
%RowNum%.Insert(field%A_Index%)
Loop, %ColumnsCount%
field%A_Index% =
oTable.Insert(%RowNum%)
}
return oTable
}
Table_Base(list, prefix) {
base := Object()
Loop Parse, list, %A_Space%
base[A_LoopField] := prefix A_LoopField
Return base
}
;====== oTable methods ======
Table_mTable_StringReplace(oTable,params*) { ; replaces "param1" with "param2", "param3" with "param4" (etc.) in all fields in table object
For k,v in oTable
{
if k is not integer ;Rows are integers.
continue
For k2,v2 in oTable[k] ; v2 = field
{
c := 0
For k3,v3 in params
{
c++
if c = 1
{
st := v3
continue
}
rt := v3, c := 0
StringReplace, v2, v2, %st%, %rt%, all
}
oTable[k][k2] := v2
}
}
}
Table_mTable_Open(oTable) { ; opens table's constructor file in Notepad if it exists
FilePath := oTable.FilePath
IfExist, %FilePath%
Run, notepad "%FilePath%"
}
Table_mTable_Save(oTable) { ; converts table object to string and saves it to its constructor file. Use only if oTable is created from file.
FilePath := oTable.FilePath ; automatically stored when creating oTable from file
if (FilePath = "")
return
ColumnsDelimiter := oTable.ColumnsDelimiter, RowsDelimiter := oTable.RowsDelimiter
oTable.SaveAs(FilePath)
return 1
}
Table_mTable_SaveAs(oTable, FilePath, ColumnsDelimiter="", RowsDelimiter= "") { ; converts table object to string and saves it to specified file
if ColumnsDelimiter =
ColumnsDelimiter := oTable.ColumnsDelimiter
if RowsDelimiter =
RowsDelimiter := oTable.RowsDelimiter
FileContents := oTable.HeaderToString(ColumnsDelimiter) RowsDelimiter oTable.ToString(ColumnsDelimiter, RowsDelimiter)
oFile := FileOpen(FilePath, "w `n", "UTF-8") ; creates a new file, overwriting any existing file.
oFile.Write(FileContents)
oFile.Close()
}
Table_mTable_Reload(ByRef oTable) { ; reads table's constructor file again and reconstructs table object if constructor file exists
static TableBase := Table_Base("HeaderToString StringReplace Search ToString ToListView NewFromScheme AddRow InsertRow ModifyRow DeleteRow Col2Num Row2Num Open Save SaveAs Reload Row2NumL LVSelInfo LVDelete LVAdd LVModify1 LVModify2", "Table_mTable_")
static RowBase := Table_Base("ToString ToListView", "Table_mRow_")
FilePath := oTable.FilePath, ColumnsDelimiter := oTable.ColumnsDelimiter, RowsDelimiter := oTable.RowsDelimiter ; collect info from old table object
IfNotExist, %FilePath% ; if constructor file doesn't exist
return ; return and leave old table object as is
oTable = ; destroy old table object
; reconstruct table object
oTable := Object("base", Tablebase, "ColumnsDelimiter", ColumnsDelimiter, "RowsDelimiter", RowsDelimiter)
oColumnNames := Object()
oTable.FilePath := FilePath
oFile := FileOpen(FilePath, "r `n", "UTF-8")
InputVariable := oFile.Read()
oFile.Close()
Loop, parse, InputVariable, %RowsDelimiter%
{
CurRow := A_LoopField
if A_index = 1 ; column names are specified as first row
{
Loop, parse, CurRow, %ColumnsDelimiter%
{
oColumnNames.Insert(A_LoopField)
ColumnsCount++
}
oTable.ColumnNames := oColumnNames
continue
}
RowNum := A_index-1
%RowNum% := Object("base", RowBase, "table", oTable)
StringSplit, field, CurRow, %ColumnsDelimiter%
Loop, %ColumnsCount%
%RowNum%.Insert(field%A_Index%)
Loop, %ColumnsCount%
field%A_Index% =
oTable.Insert(%RowNum%)
}
return oTable ; not necessary as first param is ByRef, but keep it
}
Table_mTable_AddRow(oTable,Fields*) { ; adds new row to table (to the bottom)
static RowBase := Table_Base("ToString ToListView", "Table_mRow_")
NewRowNum := oTable.MaxIndex() + 1
%NewRowNum% := Object("base", RowBase, "table", oTable)
TotalColumns := oTable.ColumnNames.MaxIndex()
For k,v in Fields
{
if (A_index > TotalColumns)
break
%NewRowNum%.Insert(v)
}
oTable.Insert(%NewRowNum%)
return NewRowNum
}
Table_mTable_InsertRow(oTable, NewRowNum ,Fields*) { ; inserts new row in table
static RowBase := Table_Base("ToString ToListView", "Table_mRow_")
if NewRowNum = 0 ; not allowed
return
if (NewRowNum > oTable.MaxIndex())
NewRowNum := oTable.MaxIndex() + 1 ; add as last row
%NewRowNum% := Object("base", RowBase, "table", oTable)
TotalColumns := oTable.ColumnNames.MaxIndex()
For k,v in Fields
{
if (A_index > TotalColumns)
break
%NewRowNum%.Insert(v)
}
oTable.Insert(NewRowNum, %NewRowNum%)
}
Table_mTable_ModifyRow(oTable, RowToModifyNumber, Fields*) { ; modifies row(s)
static RowBase := Table_Base("ToString ToListView", "Table_mRow_")
oModifyedRow := Object("base", RowBase, "table", oTable)
TotalColumns := oTable.ColumnNames.MaxIndex()
For k,v in Fields
{
if (A_index > TotalColumns)
break
oModifyedRow.Insert(v)
}
if RowToModifyNumber = 0 ; modify all existing rows
{
Loop, % oTable.MaxIndex()
oTable[A_Index] := oModifyedRow
}
else ; modify specified row
oTable[RowToModifyNumber] := oModifyedRow
}
Table_mTable_DeleteRow(oTable, RowToDeleteNumber="") { ; deletes row(s)
if (RowToDeleteNumber = 0) ; delete all existing rows
{
oTable.Remove(1, oTable.MaxIndex())
return
}
Else if (RowToDeleteNumber = "") ; delete last row
{
oDeletedRow := Object()
LastRN := oTable.MaxIndex()
oDeletedRow := oTable[LastRN]
oTable.Remove(LastRN)
return oDeletedRow
}
else ; delete specified row
{
oDeletedRow := Object()
oDeletedRow := oTable[RowToDeleteNumber]
oTable.Remove(RowToDeleteNumber)
return oDeletedRow
}
}
Table_mTable_Col2Num(oTable, ColumnsToSearch) { ; converts column name(s) to column number(s)
StringReplace, ColumnsToSearch, ColumnsToSearch, `,, `,`,, all
StringReplace, ColumnsToSearch, ColumnsToSearch, |, `,, all
For k,v in oTable.ColumnNames
{
if v in %ColumnsToSearch%
Found .= k "|"
}
return RTrim(Found, "|")
}
Table_mTable_Row2Num(oTable, Fields*) { ; converts row identified by its fields to number. First matching.
TotalColumns := oTable.ColumnNames.MaxIndex()
For k,v in Fields
{
if (A_index > TotalColumns)
break
RowStringToSearch .= v
}
For k,v in oTable
{
if k is not integer ;Rows are integers.
continue
For k2,v2 in oTable[k]
RowString .= v2
if (RowString = RowStringToSearch)
return k
RowString =
}
}
Table_mTable_NewFromScheme(oTable) { ; creates new empty table from table object template
oNewTable := Object("base", oTable.base, "ColumnsDelimiter", oTable.ColumnsDelimiter
, "RowsDelimiter", oTable.RowsDelimiter, "ColumnNames", oTable.ColumnNames)
return oNewTable
}
Table_mTable_Search(oTable, ColumnsToSearch, StringsToSearch, MatchType="containing") { ; performs search through columns or whole table
/* Parameters:
ColumnsToSearch "|" delimited list of columns to search. If empty (""), search through whole table (all columns.)
StringsToSearch "|" delimited list of strings to search except in RegEx MatchType.
MatchType Containing, Exactly, StartingWith, EndingWith, RegEx,
Containing+, Exactly+, StartingWith+, EndingWith+
"+" suffix means more permissive match type where spaces, tabs, newlines and carriage returns are not relevant for match.
*/
static RowBase := Table_Base("ToString ToListView", "Table_mRow_")
oFound := oTable.NewFromScheme() ; create empty table from oTable template
If (ColumnsToSearch = "") ; search through all columns - whole table.
{
For k,v in oTable.ColumnNames
ColumnsToSearch .= A_Index "|"
ColumnsToSearch := RTrim(ColumnsToSearch,"|")
}
else ; search through specified columns
ColumnsToSearch := oTable.Col2Num(ColumnsToSearch)
If (SubStr(MatchType,0) = "+") ; more permissive match type where spaces, tabs, newlines and carriage returns are not relevant for match.
Table_StringReplace(StringsToSearch, A_Space, "", A_Tab, "", "`n", "", "`r", "") ; like RegExReplace(StringsToSearch, "\s")
if MatchType in Containing,Exactly,Containing+,Exactly+ ; prepare matchlist
{
StringReplace, StringsToSearch, StringsToSearch, `,, `,`,, all
StringReplace, StringsToSearch, StringsToSearch, |, `,, all
}
; About coding style below: longer way, but better performance due to less "if evaluations" in loop for MatchTypes not containing "+".
if MatchType = Containing
{
For k in oTable
{
if k is not integer ;Rows are integers.
continue
Loop, parse, ColumnsToSearch, |
{
CurField := oTable[k][A_LoopField]
if CurField contains %StringsToSearch%
{
%k% := Object("base", RowBase, "table", oTable)
For k2,v2 in oTable[k]
%k%.Insert(v2)
oFound.Insert(%k%)
oFound.LastFound := oFound.LastFound "," k
}
}
}
}
else if MatchType = Exactly
{
For k in oTable
{
if k is not integer ;Rows are integers.
continue
Loop, parse, ColumnsToSearch, |
{
CurField := oTable[k][A_LoopField]
if CurField in %StringsToSearch%
{
%k% := Object("base", RowBase, "table", oTable)
For k2,v2 in oTable[k]
%k%.Insert(v2)
oFound.Insert(%k%)
oFound.LastFound := oFound.LastFound "," k
}
}
}
}
else if MatchType = StartingWith
{
For k in oTable
{
if k is not integer ;Rows are integers.
continue
Loop, parse, ColumnsToSearch, |
{
CurField := oTable[k][A_LoopField]
Loop, parse, StringsToSearch, "|"
{
if (SubStr(CurField,1,StrLen(A_LoopField)) = A_LoopField)
{
%k% := Object("base", RowBase, "table", oTable)
For k2,v2 in oTable[k]
%k%.Insert(v2)
oFound.Insert(%k%)
oFound.LastFound := oFound.LastFound "," k
}
}
}
}
}
else if MatchType = EndingWith
{
For k in oTable
{
if k is not integer ;Rows are integers.
continue
Loop, parse, ColumnsToSearch, |
{
CurField := oTable[k][A_LoopField]
Loop, parse, StringsToSearch, "|"
{
if (SubStr(CurField, - (StrLen(A_LoopField) - 1)) = A_LoopField)
{
%k% := Object("base", RowBase, "table", oTable)
For k2,v2 in oTable[k]
%k%.Insert(v2)
oFound.Insert(%k%)
oFound.LastFound := oFound.LastFound "," k
}
}
}
}
}
else if MatchType = Containing+
{
For k in oTable
{
if k is not integer ;Rows are integers.
continue
Loop, parse, ColumnsToSearch, |
{
CurField := oTable[k][A_LoopField]
Table_StringReplace(CurField, A_Space, "", A_Tab, "", "`n", "", "`r", "")
if CurField contains %StringsToSearch%
{
%k% := Object("base", RowBase, "table", oTable)
For k2,v2 in oTable[k]
%k%.Insert(v2)
oFound.Insert(%k%)
oFound.LastFound := oFound.LastFound "," k
}
}
}
}
else if MatchType = Exactly+
{
For k in oTable
{
if k is not integer ;Rows are integers.
continue
Loop, parse, ColumnsToSearch, |
{
CurField := oTable[k][A_LoopField]
Table_StringReplace(CurField, A_Space, "", A_Tab, "", "`n", "", "`r", "")
if CurField in %StringsToSearch%
{
%k% := Object("base", RowBase, "table", oTable)
For k2,v2 in oTable[k]
%k%.Insert(v2)
oFound.Insert(%k%)
oFound.LastFound := oFound.LastFound "," k
}
}
}
}
else if MatchType = StartingWith+
{
For k in oTable
{
if k is not integer ;Rows are integers.
continue
Loop, parse, ColumnsToSearch, |
{
CurField := oTable[k][A_LoopField]
Table_StringReplace(CurField, A_Space, "", A_Tab, "", "`n", "", "`r", "")
Loop, parse, StringsToSearch, "|"
{
if (SubStr(CurField,1,StrLen(A_LoopField)) = A_LoopField)
{
%k% := Object("base", RowBase, "table", oTable)
For k2,v2 in oTable[k]
%k%.Insert(v2)
oFound.Insert(%k%)
oFound.LastFound := oFound.LastFound "," k
}
}
}
}
}
else if MatchType = EndingWith+
{
For k in oTable
{
if k is not integer ;Rows are integers.
continue
Loop, parse, ColumnsToSearch, |
{
CurField := oTable[k][A_LoopField]
Table_StringReplace(CurField, A_Space, "", A_Tab, "", "`n", "", "`r", "")
Loop, parse, StringsToSearch, "|"
{
if (SubStr(CurField, - (StrLen(A_LoopField) - 1)) = A_LoopField)
{
%k% := Object("base", RowBase, "table", oTable)
For k2,v2 in oTable[k]
%k%.Insert(v2)
oFound.Insert(%k%)
oFound.LastFound := oFound.LastFound "," k
}
}
}
}
}
else if MatchType = RegEx
{
For k in oTable
{
if k is not integer ;Rows are integers.
continue
Loop, parse, ColumnsToSearch, |
{
CurField := oTable[k][A_LoopField]
if RegExMatch(CurField, StringsToSearch) ; StringsToSearch = NeedleRegEx
{
%k% := Object("base", RowBase, "table", oTable)
For k2,v2 in oTable[k]
%k%.Insert(v2)
oFound.Insert(%k%)
oFound.LastFound := oFound.LastFound "," k
}
}
}
}
oFound.LastFound := LTrim(oFound.LastFound, ",") ; stores row numbers of found rows in latest search
return oFound
}
Table_mTable_HeaderToString(oTable, ColumnsDelimiter="") { ; converts table's header (first row) to string
if ColumnsDelimiter =
ColumnsDelimiter := oTable.ColumnsDelimiter
For k,v in oTable.ColumnNames
Header .= v ColumnsDelimiter
return RTrim(Header, ColumnsDelimiter)
}
Table_mTable_ToString(oTable, ColumnsDelimiter="", RowsDelimiter= "") { ; converts table object to string
if ColumnsDelimiter =
ColumnsDelimiter := oTable.ColumnsDelimiter
if RowsDelimiter =
RowsDelimiter := oTable.RowsDelimiter
For k,v in oTable
{
if k is not integer ;Rows are integers.
continue
For k2,v2 in oTable[k]
RowString .= v2 ColumnsDelimiter
RowString := RTrim(RowString, ColumnsDelimiter)
TableString .= RowString RowsDelimiter
RowString =
}
return RTrim(TableString, RowsDelimiter)
}
Table_mTable_ToListView(oTable) { ; puts table object to ListView
For k,v in oTable
{
if k is not integer ;Rows are integers.
continue
For k2,v2 in oTable[k]
{
f%A_index% := v2
TotalFields ++
}
LV_Add("",f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30)
Loop, %TotalFields%
f%A_index% =
TotalFields =
}
}
Table_mTable_Row2NumL(oTable, RowNumToSearch, Fields*) { ; converts row identified by its fields to number but searches only through specified row numbers (limit). First matching. RowNumToSearch should be oFound.LastFound's value.
TotalColumns := oTable.ColumnNames.MaxIndex()
For k,v in Fields
{
if (A_index > TotalColumns)
break
RowStringToSearch .= v
}
if (RowNumToSearch = "") ; search through all rows
return oTable.Row2Num(Fields*)
Loop, parse, RowNumToSearch, | ; search through specified rows
{
For k2,v2 in oTable[A_LoopField]
RowString .= v2
if (RowString = RowStringToSearch)
return A_LoopField
RowString =
}
}
Table_mTable_LVSelInfo(oTable, RowNumToSearch="") { ; gets info about selected rows in ListView
Loop, % LV_GetCount("Column") ; total number of columns in LV
FromColumns .= A_Index "|"
FromColumns := RTrim(FromColumns,"|")
; oSelected structure: o1SelRow, o2SelRow, o3SelRow, etc.
; oSelRow structure: [1] oTableRowNum [2] LVRowNum [3,4,5 etc.] FieldsText
oSelected := Object()
Loop
{
RowNumber := LV_GetNext(RowNumber)
if !RowNumber
break
oSelRow := A_Index
%oSelRow% := Object() ; oSelRow
%oSelRow%.Insert("") ; [1] oTable RowNum - dummy
%oSelRow%.Insert(RowNumber) ; [2] LV owNum
oFields := Object()
Loop, parse, FromColumns, |
{
LV_GetText(FieldText, RowNumber, A_LoopField)
oFields.Insert(FieldText)
%oSelRow%.Insert(FieldText)
}
%oSelRow%[1] := oTable.Row2NumL(RowNumToSearch, oFields*) ; [1] oTable RowNum - real
oSelected.Insert(%oSelRow%), oFields := ""
}
return oSelected
}
Table_mTable_LVDelete(oTable, RowNumToSearch="") { ; deletes selected row from oTable and ListView. Deletes just 1. selected row for now.
oSelected := oTable.LVSelInfo(RowNumToSearch)
For k,v in oSelected ; oSelected structure: o1SelRow, o2SelRow, o3SelRow, etc.
{
; structure: [1] oTableRowNum [2] LVRowNum [3,4,5 etc.] FieldsText
for k2,v2 in oSelected[k]
{
if A_index = 1 ; [1] oTableRowNum
oTable.DeleteRow(v2)
else if A_index = 2 ; [2] LVRowNum
LV_Delete(v2)
else
break ; [3,4,5 etc.] FieldsText - not relevant
}
return oSelected.1 ; allow deleting just 1. selected row for now. Ignore other. Return info about deleted row.
}
}
Table_mTable_LVAdd(oTable, Fields*) { ; adds new row to oTable and ListView
; add to oTable
oTable.AddRow(Fields*)
; add to ListView
TotalColumns := oTable.ColumnNames.MaxIndex()
For k,v in Fields
{
if (A_index > TotalColumns)
break
f%A_index% := v
}
LV_Add("",f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30)
}
Table_mTable_LVModify1(oTable, RowNumToSearch="") { ; Returns row's to modify fields. Must be called prior to oTable.LVModify2()
; Relevant for machine: stores oTableRowNum and LVRowNum in oTable.LVModifyRowNums
; for faster performance when displaying search results in LV, specify oFound.LastFound as RowNumToSearch
oSelected := oTable.LVSelInfo(RowNumToSearch)
oFields := Object(), oRowNums := Object()
For k,v in oSelected.1 ; first selected row info
{
if A_index = 1 ; [1] oTableRowNum
oRowNums.Insert(v)
else if A_index = 2 ; [2] LVRowNum
oRowNums.Insert(v)
else ; [3,4,5 etc.] FieldsText
oFields.Insert(v)
}
oTable.LVModifyRowNums := oRowNums ; info used by oTable.LVModify2
return oFields ; return row's to modify fields
}
Table_mTable_LVModify2(oTable, oNewFields) { ; modifies row in ListView and oTable
TableRowNum := oTable.LVModifyRowNums.1 ; [1] oTableRowNum
LVRowNum := oTable.LVModifyRowNums.2 ; [2] LVRowNum
oTable.ModifyRow(TableRowNum, oNewFields*)
For k,v in oNewFields
f%k% := v
LV_Modify(LVRowNum,"",f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30)
}
;====== oRow methods ======
Table_mRow_ToString(oRow, ColumnsDelimiter="") { ; converts row object to string
if ColumnsDelimiter =
ColumnsDelimiter := oRow.table.ColumnsDelimiter
For k,v in oRow
{
if k is not integer ; field keys are integers.
continue
RowString .= v ColumnsDelimiter
}
return RTrim(RowString, ColumnsDelimiter)
}
Table_mRow_ToListView(oRow) { ; puts row object to ListView
For k,v in oRow
{
if k is not integer ; field keys are integers.
continue
f%k% := v
}
LV_Add("",f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30)
}
;====== Shared, other ======
Table_StringReplace(ByRef String, params*) { ; replaces "param1" with "param2", "param3" with "param4" (etc.) in string
For k,v in params
{
c++
if c = 1
{
st := v
continue
}
rt := v, c := 0
StringReplace, String, String, %st%, %rt%, all
}
}
SplitToObj(String,Delimiter="|") {
obj := Object()
Loop, parse, String, %Delimiter%
obj.Insert(A_LoopField)
return obj
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ExitApp
Pause::
Suspend
Pause,,1
return
Escape::
Suspend
ExitApp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
History:
- version 0.18 - release date 09.01.2011.
- version 0.15 - release date 29.12.2010.
- version 0.14 - release date 28.12.2010.
- version 0.13 - release date 28.12.2010.