SQL sorgusuyla Kod Kısaltma

tamer42

Destek Ekibi
Destek Ekibi
Katılım
11 Mart 2005
Mesajlar
3,189
Excel Vers. ve Dili
Office 2013 İngilizce
Merhabalar,
Ekli dosyada verilerin bulunduğu 3 adet sayfa bulunmakta;
"TEK ÖDEME", "ÇİFT ÖDEME", "KONSİNYE"

bu sayfalardaki verileri Rapor olarak çekmek için; ekli dosya Rapor sayfasında olduğu gibi verileri çekmek istiyordum, bunu aşağıdaki iki farklı prosedür ile yaptım.

Önce "getData" SQL sorgusuyla Data sayfasına yukarından aşağıya çektim, Data sayfasından sonra "OrganizeData" prosedürü ile Rapor sayfasına aldım.

Bu işlemi tek adımda SQL sorgusuyla yapabilmenin bir yolu var mıdır?

Desteğiniz için şimdiden teşekkürler,

iyi Çalışmalar dilerim.

Kod:
Sub getData()
Dim RS As Object

Dim QRY As String
Dim SQL As String
Dim x As Integer
Dim baslik As Variant
Dim fields As String

Baglan

SHT.Cells.ClearContents

arrSht = Array("TEK ÖDEME", "ÇİFT ÖDEME", "KONSİNYE")

fields = "Format([TARİH], 'dd.mm.yyyy') AS TARİH,[SATICI AD], SUM([KONSİNYE NET]) AS TOPLAM_KONSİNYE_NET"

QRY = "Where [TARİH] is Not Null Group By [TARİH], [SATICI AD]"

SQL = "SELECT " & fields & ",'" & CStr(arrSht(0)) & "' AS SAYFA From [" & arrSht(0) & "$A2:E] " & QRY
SQL = SQL & "Union ALL SELECT " & fields & ",'" & CStr(arrSht(1)) & "' AS SAYFA From [" & arrSht(1) & "$A2:E] " & QRY
SQL = SQL & "Union ALL SELECT " & fields & ",'" & CStr(arrSht(2)) & "' AS SAYFA From [" & arrSht(2) & "$A2:E] " & QRY

Set RS = Con.Execute(SQL)

SHT.Range("A2").CopyFromRecordset RS

x = 1
For Each baslik In RS.fields
        SHT.Cells(1, x) = baslik.Name
        x = x + 1
Next baslik

QRY = ""
SQL = ""
Set RS = Nothing

''OrganizeData

MsgBox "İşlem Tamam!", vbInformation, "Bilgi"
End Sub
Kod:
Sub OrganizeData()
Dim SH As Worksheet
Dim myRange As Range, Rng3 As Range
Dim Rng1 As Range, Rng2 As Range
Dim tarih As Variant, isim As String
Dim LastRow As Long, i As Long
Dim deger As String, sonuc As Variant
Dim coll As New Collection


''Set SHT = ThisWorkbook.Sheets("Data")
Set SH = ThisWorkbook.Sheets("Rapor")

SH.Range("A2:F100000").ClearContents

''arrSht = Array("TEK ÖDEME", "ÇİFT ÖDEME", "KONSİNYE")

LastRow = SHT.Cells(SHT.Rows.Count, "A").End(xlUp).Row


Set myRange = SHT.Range("C2:C" & LastRow)
Set Rng1 = SHT.Range("A2:A" & LastRow)
Set Rng2 = SHT.Range("B2:B" & LastRow)
Set Rng3 = SHT.Range("D2:D" & LastRow)


On Error Resume Next

For i = 2 To LastRow

    deger = CStr(SHT.Cells(i, 1).Value & "|" & SHT.Cells(i, 2).Value)

    coll.Add deger, deger

Next i

On Error GoTo 0


For i = 2 To coll.Count

    sonuc = Split(coll(i), "|")
    
    isim = sonuc(1)
    tarih = Format(CDate(sonuc(0)), "dd.mm.yyyy")

    SH.Cells(i, 1).Value = tarih
    SH.Cells(i, 2).Value = isim
    
    With Application.WorksheetFunction
        SH.Cells(i, 3).Value = .SumIfs(myRange, Rng1, tarih, Rng2, isim, Rng3, arrSht(0))
        SH.Cells(i, 4).Value = .SumIfs(myRange, Rng1, tarih, Rng2, isim, Rng3, arrSht(1))
        SH.Cells(i, 5).Value = .SumIfs(myRange, Rng1, tarih, Rng2, isim, Rng3, arrSht(2))
    End With
    
    
    isim = ""
    sonuc = Empty

Next i

Set coll = Nothing

Set Rng1 = Nothing
Set Rng2 = Nothing
Set Rng3 = Nothing
Set myRange = Nothing

Set SH = Nothing


End Sub
 

Ekli dosyalar

muhasebeciyiz

Altın Üye
Katılım
10 Şubat 2006
Mesajlar
1,072
Excel Vers. ve Dili
Office 2016
64 Bit
Altın Üyelik Bitiş Tarihi
21-12-2027
Tamer hocam ; YZ önerisi şöyle

Tek bir SQL sorgusuyla istediğiniz bu pivot tablo benzeri yapıyı doğrudan oluşturamazsınız.
Bunun sebebi, SQL sorgularının, verileri pivotlanmış veya çapraz tablolu bir formatta değil, düz ve normalleştirilmiş bir tablo formatında döndürmek üzere tasarlanmış olmasıdır. TEK ÖDEME, ÇİFT ÖDEME, ve KONSİNYE gibi ayrı sütunlar halinde elde etmeye çalıştığınız yapı, temel bir SELECT ifadesinin dışında gerçekleşen bir veri dönüşümünü gerektirir.Mevcut iki adımlı yaklaşımınız, bu amaca ulaşmak için yaygın ve etkili bir yoldur.
  1. getData: Bu adım, üç sayfadan gelen verileri birleştirmek ve tek, düz bir tabloda gruplamak için SQL kullanır. Bu, tam olarak SQL'in başarılı olduğu bir görevdir.
  2. OrganizeData: Bu adım ise, Data sayfasındaki düz veriyi alır ve pivotlar. Satırlar arasında döngü yaparak, her bir kategori (TEK ÖDEME, ÇİFT ÖDEME, KONSİNYE) için değerleri bulur ve toplar, sonra da bunları ayrı sütunlara yerleştirir. Bu görev, VBA'nın döngü ve sayfa fonksiyonları için oldukça uygundur.
Her ne kadar PIVOT veya CASE ifadeleri gibi daha gelişmiş SQL kavramları bu tür dönüşümleri gerçekleştirebilse de, bunlar Excel çalışma kitaplarını sorgularken kullanılan ACE.OLEDB.12.0 sağlayıcısı tarafından desteklenmez. Bu sağlayıcının yetenekleri daha sınırlıdır ve tam teşekküllü bir veritabanı sistemi (örneğin SQL Server veya Oracle) tarafından sunulan gelişmiş işlevleri içermez.
Kısacası, mevcut iki adımlı süreciniz, VBA ve ADO kullanarak Excel dosyasına bağlanarak bu görevi gerçekleştirmenin en pratik ve verimli yoludur.

iki aşamalı yaklaşım bu sorunun en güvenilir ve etkili çözümüdür:
  1. Verileri Birleştirin: Üç ayrı sayfadan (TEK ÖDEME, ÇİFT ÖDEME, KONSİNYE) gelen verileri tek bir düz tablo halinde çekin. Bu, her satırın tarih, satıcı adı, miktar ve kaynağın adını (SAYFA) içerdiği bir yapıdır. SQL'in UNION ALL komutu bu iş için idealdir.
  2. Verileri Dönüştürün: OrganizeData prosedürünüzde yaptığınız gibi, bu düz tabloyu alın ve SumIfs gibi Excel fonksiyonlarını kullanarak pivot hale getirin. Bu, her bir tarih ve satıcı kombinasyonu için her bir kaynak sayfanın (TEK ÖDEME, ÇİFT ÖDEME, KONSİNYE) verilerini ayrı sütunlara toplayacaktır.
Bu yöntem, her bir adım için en uygun aracı kullanır: veritabanı işlemlerini yapmak için SQL'i ve karmaşık veri düzenleme işlemlerini yapmak için VBA ve Excel fonksiyonlarını. Bu, hem kodunuzu daha anlaşılır hale getirir hem de ACE OLEDB'nin sınırlılıklarını aşmanızı sağlar.
 

Korhan Ayhan

Administrator
Yönetici
Admin
Katılım
15 Mart 2005
Mesajlar
43,334
Excel Vers. ve Dili
Microsoft 365 Tr-En 64 Bit
Merhaba,

Tek sorguda istediğiniz biçimde rapor için aşağıdaki kodu deneyebilirsiniz.

C++:
Option Explicit

Sub Get_Data()
    Dim My_Connection As Object
    Dim RS As Object
    Dim SQL As String
    Dim X As Integer
    Dim X_Headers As Variant
    Dim X_Fields As String
    Dim S1 As Worksheet
    
    Application.ScreenUpdating = False
    
    Set My_Connection = VBA.CreateObject("AdoDb.Connection")
    
    My_Connection.Open "Provider=Microsoft.Ace.OleDb.12.0;Data Source=" & _
    ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;Hdr=Yes"""
    
    Set S1 = Sheets("Rapor")
    
    S1.Cells.ClearContents
    
    X_Fields = "[TARİH],[SATICI AD]," & _
               "SUM(IIF(SAYFA='TEK ÖDEME',[TOPLAM_KONSİNYE_NET],0)) AS [TEK ÖDEME]," & _
               "SUM(IIF(SAYFA='ÇİFT ÖDEME',[TOPLAM_KONSİNYE_NET],0)) AS [ÇİFT ÖDEME]," & _
               "SUM(IIF(SAYFA='KONSİNYE',[TOPLAM_KONSİNYE_NET],0)) AS [KONSİNYE]"
    
    SQL = "SELECT " & X_Fields & _
          " FROM (" & _
          " SELECT [TARİH],[SATICI AD],SUM([KONSİNYE NET]) AS [TOPLAM_KONSİNYE_NET],'TEK ÖDEME'  AS SAYFA FROM [TEK ÖDEME$A2:E]  WHERE [TARİH] IS NOT NULL GROUP BY [TARİH],[SATICI AD] " & _
          " UNION ALL " & _
          " SELECT [TARİH],[SATICI AD],SUM([KONSİNYE NET]) AS [TOPLAM_KONSİNYE_NET],'ÇİFT ÖDEME' AS SAYFA FROM [ÇİFT ÖDEME$A2:E] WHERE [TARİH] IS NOT NULL GROUP BY [TARİH],[SATICI AD] " & _
          " UNION ALL " & _
          " SELECT [TARİH],[SATICI AD],SUM([KONSİNYE NET]) AS [TOPLAM_KONSİNYE_NET],'KONSİNYE'   AS SAYFA FROM [KONSİNYE$A2:E]  WHERE [TARİH] IS NOT NULL GROUP BY [TARİH],[SATICI AD] " & _
          ") AS My_Table " & _
          "GROUP BY [TARİH],[SATICI AD] " & _
          "ORDER BY [TARİH],[SATICI AD]"
    
    Set RS = My_Connection.Execute(SQL)
    
    S1.Range("A2").CopyFromRecordset RS
    
    For Each X_Headers In RS.Fields
        X = X + 1
        S1.Cells(1, X).Font.Bold = True
        S1.Cells(1, X) = X_Headers.Name
    Next
    
    S1.Range("C2:E" & S1.Cells(S1.Rows.Count, 1).End(3).Row).Style = "Comma"
    S1.Columns.AutoFit
    
    RS.Close
    My_Connection.Close
    
    SQL = ""
    Set RS = Nothing
    Set My_Connection = Nothing

    Application.ScreenUpdating = True

    MsgBox "İşleminiz tamamlanmıştır.", vbInformation, "Bilgi"
End Sub
 

tamer42

Destek Ekibi
Destek Ekibi
Katılım
11 Mart 2005
Mesajlar
3,189
Excel Vers. ve Dili
Office 2013 İngilizce
Merhaba,

Tek sorguda istediğiniz biçimde rapor için aşağıdaki kodu deneyebilirsiniz.

C++:
Option Explicit

Sub Get_Data()
    Dim My_Connection As Object
    Dim RS As Object
    Dim SQL As String
    Dim X As Integer
    Dim X_Headers As Variant
    Dim X_Fields As String
    Dim S1 As Worksheet
   
    Application.ScreenUpdating = False
   
    Set My_Connection = VBA.CreateObject("AdoDb.Connection")
   
    My_Connection.Open "Provider=Microsoft.Ace.OleDb.12.0;Data Source=" & _
    ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;Hdr=Yes"""
   
    Set S1 = Sheets("Rapor")
   
    S1.Cells.ClearContents
   
    X_Fields = "[TARİH],[SATICI AD]," & _
               "SUM(IIF(SAYFA='TEK ÖDEME',[TOPLAM_KONSİNYE_NET],0)) AS [TEK ÖDEME]," & _
               "SUM(IIF(SAYFA='ÇİFT ÖDEME',[TOPLAM_KONSİNYE_NET],0)) AS [ÇİFT ÖDEME]," & _
               "SUM(IIF(SAYFA='KONSİNYE',[TOPLAM_KONSİNYE_NET],0)) AS [KONSİNYE]"
   
    SQL = "SELECT " & X_Fields & _
          " FROM (" & _
          " SELECT [TARİH],[SATICI AD],SUM([KONSİNYE NET]) AS [TOPLAM_KONSİNYE_NET],'TEK ÖDEME'  AS SAYFA FROM [TEK ÖDEME$A2:E]  WHERE [TARİH] IS NOT NULL GROUP BY [TARİH],[SATICI AD] " & _
          " UNION ALL " & _
          " SELECT [TARİH],[SATICI AD],SUM([KONSİNYE NET]) AS [TOPLAM_KONSİNYE_NET],'ÇİFT ÖDEME' AS SAYFA FROM [ÇİFT ÖDEME$A2:E] WHERE [TARİH] IS NOT NULL GROUP BY [TARİH],[SATICI AD] " & _
          " UNION ALL " & _
          " SELECT [TARİH],[SATICI AD],SUM([KONSİNYE NET]) AS [TOPLAM_KONSİNYE_NET],'KONSİNYE'   AS SAYFA FROM [KONSİNYE$A2:E]  WHERE [TARİH] IS NOT NULL GROUP BY [TARİH],[SATICI AD] " & _
          ") AS My_Table " & _
          "GROUP BY [TARİH],[SATICI AD] " & _
          "ORDER BY [TARİH],[SATICI AD]"
   
    Set RS = My_Connection.Execute(SQL)
   
    S1.Range("A2").CopyFromRecordset RS
   
    For Each X_Headers In RS.Fields
        X = X + 1
        S1.Cells(1, X).Font.Bold = True
        S1.Cells(1, X) = X_Headers.Name
    Next
   
    S1.Range("C2:E" & S1.Cells(S1.Rows.Count, 1).End(3).Row).Style = "Comma"
    S1.Columns.AutoFit
   
    RS.Close
    My_Connection.Close
   
    SQL = ""
    Set RS = Nothing
    Set My_Connection = Nothing

    Application.ScreenUpdating = True

    MsgBox "İşleminiz tamamlanmıştır.", vbInformation, "Bilgi"
End Sub
Çok teşekkür ederim Korhan Hocam
iyi ki varsınız,
sağ olun, var olun !
 
Üst