Query naar VBA conversie tool

Status
Niet open voor verdere reacties.

JohanRVT

Gebruiker
Lid geworden
2 mrt 2011
Berichten
543
In bijlage een piepklein DB die ik (gemakkelijkheidshalve) veel gebruik om de SQL code uit een MS Access Query om te zetten via kopiëren, drukken op een knopje en plakken in de VBA module naar een VBA query.
Werkt heel goed alleen zijn de regels soms heel lang als het om een grote query gaat.
Hoe zou je de lengte van de sql string kunnen bepalen én deze dan automatisch opdelen in stukken van een bepaalde lengte zodat je de VBA code vooreerst kunt plakken in de VBA module én tegelijk goed leesbaar wordt?
De code
Code:
Private Sub cmdSql2Vba_Click()
    Dim strSql As String
    'Purpose:   Convert a SQL statement into a string to paste into VBA code.
    Const strcLineEnd = " "" & vbCrLf & _" & vbCrLf & """"
    
    If IsNull(Me.txtSql) Then
        Beep
    Else
        strSql = Me.txtSql
        strSql = Replace(strSql, """", """""")  'Double up any quotes.
        strSql = Replace(strSql, vbCrLf, strcLineEnd)
        strSql = "strSql = """ & strSql & """"
        Me.txtVBA = strSql
        Me.txtVBA.SetFocus
        RunCommand acCmdCopy
    End If
End Sub
 

Bijlagen

  • VBA Conversie.zip
    15,5 KB · Weergaven: 29
De lengte van een string kun je simpel met Len(Me.txtSQL) uitlezen. Ik weet niet of ik dat zelf zou doen op jouw manier; ik knip een opgeschoonde SQL liever zelf op. Kwestie van de eerste regel opbreken met de underscore, de volgende regel complementeren met een tab etc en de complete ‘afbreekstring’ met Copy-Paste plakken op de volgende regels op exact de plek waar ik wil afbreken. Gaat razendsnel. Jouw methode is veel te afhankelijk van waar de string al is afgebroken.
 
Een niet opgeschoonde regel zal niet geplakt kunnen worden in de VBA module wegens te lang, vandaar mijn vraag of deze automatisch kan verknipt worden.
 
Maar bestaat je vraag nog? Of kun je nu verder? Want eerlijk gezegd snap ik nog niet helemaal wat je met de lengte van de string wilt doen. Opknippen, schrijf je. Lijkt mij een riskante business, want je wilt niet midden in een woord knippen lijkt mij. Of in een commando dat je niet zomaar mag splitsen.
 
Dat is hetgeen ik bedoelde; een automatische herkenning vanaf een bepaalde lengte van een karakter/teken of zoiets in de string en dan commando dat er veilig mag geknipt worden .
 
Lijkt mij een hele lastige; dan kom je al gauw uit bij een matrix van steekwoorden waarachter je wel mag afbreken, in combinatie met de positie in de string waar dat steekwoord dan mag staan. En dat dan weer gerelateerd aan waar je nu precies wel en niet afbreekt, want aan de exacte positie heb je ook weer niet zoveel als de plek van afbreken geen constante is (omdat die dat niet kan zijn). Dus als je de eerste regel afbreekt op 50 tekens, de volgende op 62 en de daaropvolgende op 52, etc. dan heb je al zoveel variatie in waar je dan zou willen afbreken op regel 4, dat het m.i. al nauwelijks meer zinvol te programmeren is. Ik zou het lekker bij handmatig afbreken houden.
Want hoe vaak komt het nu daadwerkelijk voor dat je in de problemen komt met een af te breken sql string? Ik doe dat dus ook regelmatig, en ik ben nog nooit in de problemen gekomen. Maar ik gebruik dus de methode dat ik de eerste regel handmatig afbreek, de volgende regel laat inspringen t.o.v. de beginregel (dat kan jouw code al helemaal niet) en dat stuk van de code dan kopieer en plak op exact die positie waar ik wil dat de code wordt afgebroken. En dan heb ik binnen een minuut een complete SQL string opgeknipt.

Ik vind jouw truc om de quootjes aan te passen overigens wel handig, want dat doe ik nog handmatig en dat is nog wel opletten. Zeker omdat ik de enkele quoots altijd vervang door dubbele, een uitbreiding die ik er dus wel even bij heb gemaakt. Dus dat stuk neem ik in dankbaarheid wel over :).
 
Als dank voor het idee, hier een werkwijze die een string omzet naar hapklare brokken. Bij mij werkt-ie, dus ik denk dat jij hem ook wel werkend krijgt. Met iMin kun je instellen hoe groot de brokken ongeveer moeten zijn.
Code:
Dim strSQL As String
Dim myData As New DataObject
Dim arr As Variant, arrNew() As Variant
Const iMin As Integer = 120
Const iMax As Integer = 160
Dim iPos As Integer, iStart As Integer, iLen As Integer, iCycle As Integer
Const strcLineEnd = " "" & vbCrLf & _" & vbCrLf & vbTab & vbTab & """"
Dim i As Integer, j As Integer
'Purpose:   Convert a SQL statement into a string to paste into VBA code.
    
    If IsNull(Me.txtSQL) Then
        Beep
    Else
        arr = Split(Me.txtSQL, vbCrLf)
        ReDim arrNew(0)
        For i = LBound(arr) To UBound(arr)
            iPos = 0
            iStart = 0
            iCycle = Len(arr(i)) \ iMax
            If iCycle = 0 Then
                arrNew(UBound(arrNew)) = arr(i)
                iStart = iStart + Len(arrNew(UBound(arrNew)))
                ReDim Preserve arrNew(UBound(arrNew) + 1)
            Else
                MsgBox Len(arr(i))
                For j = 0 To iCycle
                    If j = 0 Then
                        iPos = 0
                        iStart = 0
                        iPos = InStr(iMin, arr(i), " ")
                        arrNew(UBound(arrNew)) = Left(arr(i), iPos)
                        iStart = iStart + Len(arrNew(UBound(arrNew)))
                        iStart = iPos
                    Else
                        iPos = InStr(iStart + iMin, arr(i), " ")
                        ReDim Preserve arrNew(UBound(arrNew) + 1)
                        If iPos = 0 Then iLen = Len(arr(i)) Else: iLen = iPos
                        arrNew(UBound(arrNew)) = Mid(arr(i), iStart + 1, iLen - iStart)
                        iStart = iStart + Len(arrNew(UBound(arrNew)))
                    End If
                Next j
                ReDim Preserve arrNew(UBound(arrNew) + 1)
                arrNew(UBound(arrNew)) = Right(arr(i), Len(arr(i)) - iPos)
                ReDim Preserve arrNew(UBound(arrNew) + 1)
            End If
        Next i
        For i = LBound(arrNew) To UBound(arrNew)
            If Not arrNew(i) & "" = vbNullString Then strSQL = strSQL & arrNew(i) & vbCrLf
        Next i
        strSQL = Replace(strSQL, """", """""")  'Double up any quotes.
        strSQL = Replace(strSQL, "'", """""")   'Convert any single quotes.
        strSQL = Replace(strSQL, vbCrLf, strcLineEnd)
        strSQL = vbTab & "strSQL = """ & strSQL & """"
        Me.txtVBA = strSQL
        Me.txtVBA.SetFocus
    myData.SetText txtVBA.Text
    myData.PutInClipboard
''    myData.GetFromClipboard
''    MsgBox myData.GetText(1)
''    RunCommand acCmdCopy
    End If
De hele mikmak wordt gesplitst op basis van een spatie; ik zag zo snel geen teken wat handiger is. Kijk zelf maar of je daar wat anders voor wilt gebruiken. Ik heb de copy methode vervangen; bij jouw methodiek plakte hij de complete tabel in het VBA venster! Ook wel cool :cool: trouwens :).
 
Ik krijg een compileer foutmelding van de VBA module: Expressie voor constante vereist op de regel
Code:
strSQL = Replace(strSQL, vbCrLf, strcLineEnd)
 
Die constante komt uit jouw eigen code, dus die zou moeten werken. Anders haal je de constante weg, en vervang je hem door de inhoud van de constante. Zou ook moeten werken.
 
Ja maar je hebt aan die constante met jouw code 2x een tab aan toegevoegd; zou dat de reden niet kunnen zijn? Rare is echter ook dat als ik de nieuwe regel van de const bovenaan even uitvink met een ' en de oude terugzet en compileer ik geen foutmelding meer krijg en idem als ik de zaken terug omkeer geen foutmelding meer bij compileren (waar die er eerst wel was).
De code lijkt overigens te werken; bij kopiëren van een tamelijk Query uit Access krijg ik na een msgbox van Acces met 1236 en krijg ik een vba Query die keurig verkapt is.
Trouwens er is ook een grens aan het aantal regels in zo'n VBA procedure code; ben daar al een paar keer op gebost als je ieder veldje uit zo'n query op een nieuwe regel zet om het overzichtelijk te houden.
Hoe zou je zoiets kunnen inbouwen dat dit gecheckt (+ waarschuwing gegeven) wordt bij het drukken op de knop?
 
Laatst bewerkt:
Dan lijkt de tab bij jouw de boosdoener; wellicht te maken met de Office versie? Ik heb 'm gemaakt in 2010. Ik vind het persoonlijk mooi als een afgebroken SQL string inspringt na de eerste regel, vandaar de tabs. Wil je die ook hebben, dan kun je natuurlijk ook de ASCII code gebruiken i.p.v. de constante.
Het maximum zou ik eerlijk gezegd niet weten; ik heb 'm losgelaten op behoorlijk lange strings, en nog geen problemen. In een Tekststring kun je ook aardig wat tekst kwijt, zon 65.400 tekens. Da's een hoop :). De grootte van een procedure moet binnen de 64kb vallen, dus ongeveer de lengte van een string. In een vraag die vandaag (je verzint het niet) is gesteld, ging het over de foutmelding dat de procedure te lang was. Het ging hier over een Select Case van 4000 cases. Dank je de koekoek dat dat niet loopt, zou ik zeggen :). Iemand in een forum kwam in de problemen bij een procedure met een lengte van 2300 regels. Is dus ook heel behoorlijk lang...
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan