What?
A quick article on if you were given a webpage coded in HTML, what methods in AutoHotkey could you use to separate out the HTML Tables into a ListView.

Why?
I want a snippet of code that replicates any HTML table.

How?
I've been trying various ways so I'm posting them here. My opinions on them change with the weather so until I do some benchmarking I won't know which ones best:

Method #1
This method replicates the table in a listview format:
        ; tell the script which content to parse
        Haystack := CodeContainingMyHTMLTable

        ; determine markers (character positions)
        Needle1a := "<th>My Unique Table Heading"               ; Needle1a is a marker for a unique value in the whole content
        Needle1b := "<th>"                                      ; Needle1b is a marker for a value located after Needle1a
        Needle2a := "</table>"                                  ; Needle2a is the closing marker

        ; get table HTML
        Needle1 := InStr( Haystack, Needle1a, false, NeedleMarker )
        Needle1 := InStr( Haystack, Needle1b, false, Needle1 ) + StrLen( Needle1b )
        Needle2 := InStr( Haystack, Needle2a, false, Needle1 )
        NeedleLen := Needle2 - Needle1
        NeedleMarker := Needle2
        ReturnedHTMLTable := SubStr( Haystack, Needle1, NeedleLen )

        ; split the table into rows
        StringReplace,ReturnedHTMLTableRows,ReturnedHTMLTable,</tr>,|,A
        ReturnedHTMLTableRows=%ReturnedHTMLTableRows%
        StringSplit,ReturnedHTMLTableRows,ReturnedHTMLTableRows,|
        RowIndex:=0
        Loop, %ReturnedHTMLTableRows0%
        {
            RowIndex++
            ReturnedHTMLTableColString:=ReturnedHTMLTableRows%RowIndex%

            ; split the row into columns
            StringReplace,ReturnedHTMLTableColString,ReturnedHTMLTableColString,</td>,|,A
            IfInString,ReturnedHTMLTableColString,</th>
                StringReplace,ReturnedHTMLTableColString,ReturnedHTMLTableColString,</th>,|,A

            ; get rid of new lines
            StringReplace,ReturnedHTMLTableColString,ReturnedHTMLTableColString,`n,,A
            StringReplace,ReturnedHTMLTableColString,ReturnedHTMLTableColString,`r,,A

            ; strip any remaining html
            ReturnedHTMLTableColString := RegExReplace( ReturnedHTMLTableColString, "<.+?>" , "")
            ReturnedHTMLTableColString=%ReturnedHTMLTableColString%

            ; split into an array
            StringSplit,ReturnedHTMLTableCols,ReturnedHTMLTableColString,|

            ; add to last found listview
            LV_Add("", RowIndex, ReturnedHTMLTableCols1, ReturnedHTMLTableCols2, ReturnedHTMLTableCols3, ReturnedHTMLTableCols4, ReturnedHTMLTableCols5, ReturnedHTMLTableCols6, ReturnedHTMLTableCols7, ReturnedHTMLTableCols8 )

            ; reset the array
            ReturnedHTMLTableColString=|||||||||
            StringSplit,ReturnedHTMLTableCols,ReturnedHTMLTableColString,|
        }

        LV_ModifyCol()

Method #2
This method only uses two columns with the label being a concatenation of the value of the first column and the column heading.
    StringReplace,ReturnedHTMLTableRows,ReturnedHTMLTable,,|,A
    ReturnedHTMLTableRows=%ReturnedHTMLTableRows%
    StringSplit,ReturnedHTMLTableRows,ReturnedHTMLTableRows,|
    RowIndex:=0
    Loop, %ReturnedHTMLTableRows0%
    {
        ColIndex:=1
        RowIndex++
        ReturnedHTMLTableColString:=ReturnedHTMLTableRows%RowIndex%

        If RowIndex=2
            StringSplit,HeadingsArray,HeadingsArrayString,|

        StringReplace,ReturnedHTMLTableColString,ReturnedHTMLTableColString,,|,A
        ReturnedHTMLTableColString=%ReturnedHTMLTableColString%
        StringSplit,ReturnedHTMLTableCols,ReturnedHTMLTableColString,|
        Loop, %ReturnedHTMLTableCols0%
        {
            ThisValue := RegExReplace( ReturnedHTMLTableCols%ColIndex%, "<.+?>" , "")
            HeadingIndex := ColIndex + 2
            TypeLabel := HeadingsArray%HeadingIndex%

            If RowIndex=1
                HeadingsArrayString:=HeadingsArrayString "|" ThisValue

            If ColIndex=1
                ThisLabel := ThisValue
            Else
                If RowIndex<>1
                    If ColIndex<>%ReturnedHTMLTableCols0%
                        LV_Add("", ThisLabel " (" TypeLabel ")" , ThisValue )

            ColIndex++
        }
    }


Snippets
Assume that "Haystack" is the string of code you want to parse (all content).

Function ExtractText extracts text given a unique string to mark the start of the extract (1a), a second string (1b) to refine the starting position of the extract, and a third string (2a) to specify the closing position of the extract. NeedleMarker is the offset and means when this function is used for several tables, the Needlemarker tells the function to start from where it last found a table and to find the next:
    ExtractText( Haystack, Needle1a, Needle1b, Needle2a, NeedleMarker ){

        Needle1 := InStr( Haystack, Needle1a, false, NeedleMarker )
        Needle1 := InStr( Haystack, Needle1b, false, Needle1 ) + StrLen( Needle1b )
        Needle2 := InStr( Haystack, Needle2a, false, Needle1 )
        NeedleLen := Needle2 - Needle1
        NeedleMarker := Needle2
        ThisValue := SubStr( Haystack, Needle1, NeedleLen )
        ThisValue=%ThisValue%

        Return [ThisValue, NeedleMarker]

    }


; Usage
        ; get table HTML
        ReturnedValues := ExtractText( Haystack, Needle1a, Needle1b, Needle2a, NeedleMarker )
        TheHTMLTable := ReturnedValues[1]
        NeedleMarker := ReturnedValues[2]