2012-05-04 13 views
0

SELECTステートメントへの入力として他のセルを使用して、Excelの単一セル内でSQL SELECTステートメントを実行します。いくつかの検索の後、私はsql.request関数が私が探しているものを正確に行っていることが分かった。しかし、その関数は2002年以降に廃止されました。私はここでExcel 2007と2010を動作させています。 CitationSQL.REQUEST Excel関数代替? VBAで作成しますか?

私は同じことをするマクロ/ VBAスクリプトを作成しようとしましたが、これではそれほど遠くには到達できませんでした。私はLabVIEW、Mathematica、SQLでプログラミングをすべて行います。私はVBAで何が起こっているのか分かりません。これは私が思い付くことができたものです:

Sub Test2() 

' Declare the QueryTable object. I'm not actually sure why this line is here... 
Dim qt As QueryTable 

' Set up the SQL Statement 
sqlstring = "SELECT `Substrate ID` FROM temp_table WHERE `id`=" & Range("A1").Value 

' Set up the connection string, reference an ODBC connection 
connstring = "ODBC;DSN=OWT_x64;" 

' Now implement the connection, run the query, and add 
' the results to the spreadsheet 
With ActiveSheet.QueryTables.Add(Connection:=connstring, Destination:=Range("A22"), Sql:=sqlstring) 
    .Refresh BackgroundQuery:=False 
End With 

End Sub 

上記のコードを持つ三つの主要な問題があります。

  1. は、このコードは、セルA22の列ID(「基板ID」)を返します。 、セルA23のSQLクエリの結果私は結果だけを必要とし、私はセルA22でそれを欲しい。すべてのクエリは1行と1列だけを返すように強制されます。
  2. 出力セル、A22は、スクリプトの実行時にどのセルがアクティブになるようにするかわかりません。また、入力セルA1は、アクティブセルの左(列-1)に直接セルである必要があります。
  3. 私は私の最終目標であるExcelの機能

    =sql.request(connection_string,[output_ref],[driver_prompt],[query_text],[col_names_logical])

    にこれを有効にする方法がわかりません。このようにして、私はこのコードを私の会社の他の人に与えることができ、簡単に使うことができます。

接続は、MySQL 5.6データベースへのODBC接続です。あなたは私が持っているVBAコードから見ることができるように

SELECT column FROM table WHERE id=excel_cell_value 

:クエリは非常に単純です、との線に沿って。

現在、 "id"と "Substrate ID"列のすべての行を返す別のExcelワークシートでクエリを実行し、VLOOKUPを実行して対象の項目を検索します。データベースのサイズが非常に高速になっているため、これが問題になり始めています。

だから、私は尋ねる:

  1. 私は結果で列IDを取り除くことができますどのように?
  2. これをカスタムエクセル機能にするにはどうすればよいですか?私はOffice.comを見てきましたが、それほど難しくはありませんが、まず作業スクリプトが必要です。
  3. - または - 誰でも既に共有したいカスタム機能を作っていますか?

ありがとう!

EDIT:Timのリンクのおかげで何かがうまくいくように管理しました。

Function SQLQuery(sqlString As String, connString As String, Optional TimeOut As Integer) As String 

SQLQuery = Error 'Assume an error happened 

Dim conn As ADODB.Connection 
Dim record As ADODB.Recordset 

Set conn = New ADODB.Connection 
conn.ConnectionString = connString 
conn.Open 
Set record = New ADODB.Recordset 

If TimeOut > 0 Then 
    conn.CommandTimeout = TimeOut 
End If 

record.Open sqlString, conn 

Dim cols As Long 
Dim i As Long 

cols = record.Fields.Count 'Count how many columns were returned 
If Not record.EOF Then 'Put results into comma-delimited string 
    record.MoveFirst 
    s = "" 
    If Not record.EOF Then 
     For i = 0 To cols - 1 
      s = s & IIf(i > 0, ",", "") & record(i) 
     Next i 
    End If 
End If 

SQLQuery = s 

End Function 

ただし、かなり遅いです。どのようにそれをスピードアップするための任意のアイデア?

+0

http://itknowledgeexchange.techtarget.com/beyond-excel/using-ado-to-read-a-database/ Excelでユーザー定義関数(UDF)を作成するために、ADOを使用する方法を示し –

+0

ティムが提供したリンクのおかげで、私は何かを稼働させることができました。 (編集を参照してください)ただし、複数のセルで実行するとかなり遅いです。誰でもそれを修正する方法を知っていますか? – dthor

+0

一度に1つのセルを実行するUDFは、一度にすべてのセルを更新するサブを介してクエリを実行するほど速くはありません。つまり、UDFが再計算するたびに接続を作成したり、開いたり閉じたりしますシート/ワークブック再計算ごとに1回以上)。関数内の静的変数に接続(および接続文字列)をキャッシュすることができます。したがって、次の呼び出しで同じ接続文字列を使用している場合は、新しい接続を行う必要はありません。しかし、それは決して自分自身を試みた。 –

答えて

1

ここでは、接続のキャッシュを簡単にテストします。 100ルックアップのテストワークシートでは、計算時間が約18秒から約0.5秒に短縮されました。

Excelを閉じるか、VB環境がリセットされるまで、接続は開いたままになります。

環境の違いをテストする場合は、マークされた行をコメントアウトすることもできます(VBEの「停止」ボタンを押して静的変数をクリアすることも忘れないでください)。

Function SQLQuery(sqlString As String, connString As String, _ 
            Optional TimeOut As Integer) As String 

    Static cs As String 
    Static conn As ADODB.Connection 

    SQLQuery = Error 'Assume an error happened 
    Dim s 

    If conn Is Nothing Or connString <> cs Then 
     Set conn = New ADODB.Connection 
     conn.ConnectionString = connString 
     conn.Open 
     If TimeOut > 0 Then conn.CommandTimeout = TimeOut 
     cs = connString '###comment this out to disable caching effect 
    End If 

    Dim record As New ADODB.Recordset 

    record.Open sqlString, conn 

    Dim cols As Long 
    Dim i As Long 

    cols = record.Fields.Count 'Count how many columns were returned 
    If Not record.EOF Then 'Put results into comma-delimited string 
     record.MoveFirst 
     s = "" 
     If Not record.EOF Then 
      For i = 0 To cols - 1 
       s = s & IIf(i > 0, ",", "") & record(i) 
      Next i 
     End If 
    End If 

    SQLQuery = s 

End Function 
+0

ああ、今それは素晴らしいです!これは間違いなくずっと便利です。ありがとうTim! – dthor

関連する問題