Hi Dennis,

On 2019-10-17 02:11, Harris, Dennis wrote:
I sure this has been asked a 100 times but what is the best practice to get 
data from SQLITE to Excel?  I would like to have a pivot table that updates 
upon open.


Excel and it's leading open source alternative - LibreOffice Calc, both
have build-in DB/XML datasource facilities [*]. In LibreOffice user
interface should be sufficient. For Excel 2003 (the only version I have)
I am using VBA Macro, pasted bellow.

Testing:

1.Install ODBC driver for SQLite
  This is the leading OSS driver, developed by Mr.Cristian Werner:
  http://www.ch-werner.de/sqliteodbc/

2.Save module text bellow as vb.base somewhere, then import it into your
  workbook (Alt-F11, File/Import file) [**]

3.Name a new sheet in your workbook "sqlite". Paste the following 4
  lines in column A starting from A1

```
c:\path\to\your\database.sqlite

tables_and_views select name, 'select * from ' || name sql, type from
sqlite_master where type in ('table', 'view') order by name
```

4.Select Cell A3 (containing tables_and_views), press Ctrl+Shift+d.
  Expected result is a table (name, sql) placed from A6.

5.In any cell like A6 - which contains name (suitable for a Excel
  identifier - sheet-name, QueryTable name, etc) and sql in the adjacent
  cell you can press Ctrl-d for table and Ctrl-t from pivot.

Step 4. is optional (just for illustration of what is expected on step
5.). From step 3. only the path placed in A1 is mandatory.

Hope this mess still work in your Excel version :-)

Kind Regards,
Alek

[*] IMHO, spreadsheet applications should be used primarily for
browsing/pivoting of data based on DB/XML datasources, not as
development place, where the user tries with a bunch of fragile formulas
and macros to achieve the same result as of few lines SQL.

[**] If you want these macros to be available in all workbooks, import
them in a hidden workbook placed in the path, specified at
"Tools/Options/General/At startup" (Usually persnal.xls) or something
similar in your version of Excel.


db.bas:
-------
Attribute VB_Name = "db"
Option Explicit
Private Function sheet_db_name(sheet As Excel.Worksheet)
    Select Case ActiveSheet.name
        Case "sqlite"
            sheet_db_name = sheet.range("a1")
        Case "mysql-sample"
            sheet_db_name = sheet.range("a1")
        Case Else
            sheet_db_name = ""
    End Select
End Function

Private Function connection_string(connection_key As String, Optional db_name As String) As String
    Select Case connection_key
        Case "sqlite"
            Let connection_string = _
                "ODBC;DRIVER={SQLite3 ODBC Driver};DATABASE=" & db_name
        Case "dsn-sample"
            Let connection_string = _
                "ODBC;DSN=sample;Uid=aUsername;Pwd=aPassword"
        Case "mysql-sample"
            Let connection_string = _
"ODBC;DRIVER={MySQL ODBC 5.1 Driver};SERVER=127.0.0.1;Port=3306;" _
                & "DATABASE=" & db_name & ";USER=aPassword;OPTION=3;"
        Case Else
            Let connection_string = _
                "OLEDB;Provider=SQLOLEDB; Server=127.0.0.1,1433; " & _
"User ID=aUsername; Password=aPassword; Initial Catalog=" & connection_key
    End Select
End Function

Private Function sheet_get(name As String) As Excel.Worksheet
    Dim sel As Object
    Dim sheet As Excel.Worksheet
    For Each sel In ActiveWorkbook.Sheets
        If sel.name = name Then
            Set sheet_get = sel
            Exit Function
        End If
    Next
End Function

Private Sub db_fetch( _
    sql As String, connection_key As String, _
    range_at As Excel.range, fetch_name As String, _
    Optional db_name As String = "", _
    Optional as_pivot As Boolean = False _
    )
    Dim sheet As Excel.Worksheet
    Dim db_connection_string As String

    Let db_connection_string = connection_string(connection_key, db_name)
    Set sheet = range_at.Worksheet

    If Not Err Then
        If as_pivot Then
            Dim cache As Excel.PivotCache
            Set cache = ActiveWorkbook.PivotCaches.Add(xlExternal)
            With cache
                .Connection = db_connection_string
                .CommandType = xlCmdSql
                .CommandText = sql
            End With

            Dim pivot As PivotTable
            Set pivot = sheet.PivotTables.Add(cache, range_at, fetch_name)
            Let pivot.DisplayImmediateItems = True
        Else
            With sheet.QueryTables.Add(db_connection_string, range_at, sql)
                .name = fetch_name
                .FieldNames = True
                .RowNumbers = False
                .MaintainConnection = False
                .FillAdjacentFormulas = False
                .PreserveFormatting = True
                .RefreshOnFileOpen = False
                .BackgroundQuery = False
                .RefreshStyle = xlInsertDeleteCells
                .SavePassword = True
                .SaveData = True
                .AdjustColumnWidth = True
                .RefreshPeriod = 0
                .PreserveColumnInfo = False
                .FillAdjacentFormulas = True
                Call .Refresh(BackgroundQuery:=False)
            End With
        End If
    End If
End Sub

Private Function querytable_get(sheet As Excel.Worksheet, name As String) As Excel.QueryTable
    Dim query As Excel.QueryTable
    For Each query In sheet.QueryTables
        If query.name = name Then
            Set querytable_get = query
            Exit Function
        End If
    Next
End Function

Private Sub db_fetch_sheet( _
    sheet_name As String, sql As String, connection_key As String, _
    result_name As String, _
    Optional db_name As String = "", _
    Optional as_pivot As Boolean = False, _
    Optional before As Excel.Worksheet = Nothing _
    )
    Dim sheet As Excel.Worksheet
    Dim query As Excel.QueryTable
    Dim range_at As Excel.range

    Set query = Nothing
    Set sheet = sheet_get(sheet_name)

    If sheet Is Nothing Then
        If before Is Nothing Then
            Set sheet = ActiveWorkbook.Worksheets.Add
        Else
            Set sheet = ActiveWorkbook.Worksheets.Add(before)
        End If
        Let sheet.name = sheet_name
    Else
        Set query = querytable_get(sheet, sheet_name)
    End If
    If query Is Nothing Then
        Set range_at = sheet.range(IIf(as_pivot, "a4", "a1"))
Call db_fetch(sql, connection_key, range_at, result_name, db_name, as_pivot)
        Call sheet.range("a2").Activate
        Let ActiveWindow.FreezePanes = True
    Else
        Let query.CommandText = sql
        Call query.Refresh
    End If
End Sub

Public Sub db_fetch_invoke_op(Optional as_pivot As Boolean = False)
    Dim sel As Excel.range
    Dim cell As Excel.range
    Dim connection_key As String
    Dim db_name As String
    Dim csheet As Excel.Worksheet

    Set csheet = ActiveSheet
    Let connection_key = csheet.name
    Let db_name = sheet_db_name(csheet)
    Set sel = Selection
    For Each cell In sel.Cells
Call db_fetch_sheet(cell.value, cell.Next, connection_key, cell.value, db_name, as_pivot, csheet)
    Next
End Sub

Public Sub db_fetch_invoke()
Attribute db_fetch_invoke.VB_ProcData.VB_Invoke_Func = "d\n14"
    Call db_fetch_invoke_op(False)
End Sub

Public Sub db_fetch_invoke_as_pivot()
Attribute db_fetch_invoke_as_pivot.VB_ProcData.VB_Invoke_Func = "t\n14"
    Call db_fetch_invoke_op(True)
End Sub

Public Sub db_fetch_invoke2()
Attribute db_fetch_invoke2.VB_ProcData.VB_Invoke_Func = "D\n14"
    Dim sheet As Excel.Worksheet
    Dim query As Excel.QueryTable
    Dim connection_key As String
    Dim result As Excel.range
    Dim sql_coords As String, result_coords As String
    Dim sql As String
    Dim result_name As String

    Let result_name = ActiveCell
    Set sheet = ActiveCell.Worksheet

    Let connection_key = sheet.name

    Let sql_coords = Chr(64 + ActiveCell.Column) & ActiveCell.row + 1
    Let result_coords = Chr(64 + ActiveCell.Column) & ActiveCell.row + 2
    Let sql = sheet.range(sql_coords).value
    Set result = sheet.range(result_coords)

    If result_name = "" Or sql = "" Then Exit Sub

    Set query = querytable_get(sheet, result_name)
    If query Is Nothing Then
Call db_fetch(sql, connection_key, result, result_name, sheet_db_name(ActiveSheet))
    Else
        Let query.CommandText = sql
        Call query.Refresh
    End If
End Sub


Public Function qmr(s As String, args As Excel.range) As String
    Dim c As Excel.range
    Dim v As String
    qmr = s
    For Each c In args
        If IsDate(c) Then
            v = Format(c, "yyyy-mm-dd")
        Else
            v = c
        End If
        qmr = Replace(qmr, "?", v, , 1)
    Next
End Function


_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to