Aceasta este o copie de probă. Site-ul adevărat este excel-group.ro.
Meniu
VBA avansat în Excel – automatizare rapoarte cu array-uri, Dictionary, bucle și funcții reutilizabile fără cunoștințe de programare

VBA avansat în Excel: automatizează rapoarte complexe fără să fii programator

VBA avansat în Excel: automatizează rapoarte complexe fără să fii programator

Macrourile înregistrate sunt un început bun. Dar se opresc acolo unde apare prima condiție, primul buclă, prima decizie.

VBA (Visual Basic for Applications) e limbajul care îți permite să construiești automatizări reale — rapoarte generate automat din date brute, fișiere create și salvate cu un click, emailuri trimise direct din Excel.

Acest ghid e pentru utilizatorul Excel avansat care vrea să treacă pragul de la „record macro” la cod real care rezolvă probleme reale.


Structura unui proiect VBA bine organizat

Deschizi VBA Editor: Alt+F11

Organizarea codului:

  • Module — proceduri și funcții reutilizabile (codul principal)
  • ThisWorkbook — evenimente ale registrului de lucru (Workbook_Open, BeforeSave)
  • Sheet modules — evenimente specifice foii (Worksheet_Change, SelectionChange)
  • Clase (Class Modules) — pentru cod orientat-obiect (avansat)

Convenții de denumire:

' Proceduri (nu returnează valoare):
Sub GenereazaRaportLunar()

' Funcții (returnează valoare):
Function CalculeazaTVA(suma As Double) As Double

Lucrezi cu date: citire și scriere eficientă

Cea mai mare greșeală VBA: celulă cu celulă

Lent (evită):

For i = 1 To 10000
    Cells(i, 1).Value = i * 2  ' 10.000 operații cu foaia
Next i

Rapid (folosește arrays):

Dim arr(1 To 10000, 1 To 1) As Long
For i = 1 To 10000
    arr(i, 1) = i * 2  ' operație în memorie
Next i
Range("A1:A10000").Value = arr  ' o singură scriere în foaie

Diferența de viteză: de 50-100x pe seturi mari de date.

Citire rapidă în array:

Dim data As Variant
data = Range("A1:D" & LastRow).Value  ' tot tabelul în memorie
' Acum data(rând, coloană) - accesezi instant

Funcții utilitare pe care le scrii o dată și le refolosești

LastRow și LastCol — fundamentale

Function LastRow(ws As Worksheet, Optional col As Integer = 1) As Long
    LastRow = ws.Cells(ws.Rows.Count, col).End(xlUp).Row
End Function

Function LastCol(ws As Worksheet, Optional row As Integer = 1) As Integer
    LastCol = ws.Cells(row, ws.Columns.Count).End(xlToLeft).Column
End Function

SheetExists — verifici înainte să creezi

Function SheetExists(wb As Workbook, sheetName As String) As Boolean
    Dim ws As Worksheet
    On Error Resume Next
    Set ws = wb.Sheets(sheetName)
    SheetExists = Not ws Is Nothing
    On Error GoTo 0
End Function

GetOrCreateSheet — creezi foaia dacă nu există

Function GetOrCreateSheet(wb As Workbook, sheetName As String) As Worksheet
    If SheetExists(wb, sheetName) Then
        Set GetOrCreateSheet = wb.Sheets(sheetName)
        GetOrCreateSheet.Cells.Clear
    Else
        Set GetOrCreateSheet = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
        GetOrCreateSheet.Name = sheetName
    End If
End Function

Exemplu complet: raport lunar generat automat din date brute

Scenariul: ai o foaie „Date” cu toate tranzacțiile anului. La click pe un buton, generezi automat câte o foaie separată pentru fiecare lună, cu sumarul vânzărilor per agent.

Sub GenereazaRapoarteLunare()
    Dim wsDate As Worksheet
    Dim wsRaport As Worksheet
    Dim data As Variant
    Dim i As Long, ultimulRand As Long
    Dim luna As Integer, lunaCurenta As Integer
    Dim dictLuni As Object
    
    ' Optimizare: oprim refreshul ecranului
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False
    
    Set wsDate = ThisWorkbook.Sheets("Date")
    ultimulRand = LastRow(wsDate)
    
    ' Citim tot tabelul în memorie
    data = wsDate.Range("A2:D" & ultimulRand).Value
    ' Coloana A: Data, B: Agent, C: Produs, D: Valoare
    
    ' Colectăm lunile unice
    Set dictLuni = CreateObject("Scripting.Dictionary")
    For i = 1 To UBound(data, 1)
        If IsDate(data(i, 1)) Then
            luna = Month(data(i, 1))
            If Not dictLuni.Exists(luna) Then
                dictLuni.Add luna, MonthName(luna, False)
            End If
        End If
    Next i
    
    ' Generăm câte o foaie per lună
    Dim lunii As Variant
    For Each lunii In dictLuni.Keys
        Dim numeLuna As String
        numeLuna = "Raport_" & Format(lunii, "00")
        Set wsRaport = GetOrCreateSheet(ThisWorkbook, numeLuna)
        
        ' Antet raport
        With wsRaport
            .Range("A1").Value = "Raport Vânzări " & dictLuni(lunii) & " " & Year(Now)
            .Range("A1").Font.Bold = True
            .Range("A1").Font.Size = 14
            .Range("A3:C3").Value = Array("Agent", "Nr. Tranzacții", "Total Vânzări")
            .Range("A3:C3").Font.Bold = True
        End With
        
        ' Calculăm per agent pentru luna respectivă
        Dim dictAgenti As Object
        Set dictAgenti = CreateObject("Scripting.Dictionary")
        Dim dictCount As Object
        Set dictCount = CreateObject("Scripting.Dictionary")
        
        For i = 1 To UBound(data, 1)
            If IsDate(data(i, 1)) And Month(data(i, 1)) = lunii Then
                Dim agent As String
                agent = CStr(data(i, 2))
                If Not dictAgenti.Exists(agent) Then
                    dictAgenti.Add agent, 0
                    dictCount.Add agent, 0
                End If
                dictAgenti(agent) = dictAgenti(agent) + data(i, 4)
                dictCount(agent) = dictCount(agent) + 1
            End If
        Next i
        
        ' Scriem rezultatele
        Dim randScriere As Long
        randScriere = 4
        Dim agentKey As Variant
        For Each agentKey In dictAgenti.Keys
            wsRaport.Cells(randScriere, 1).Value = agentKey
            wsRaport.Cells(randScriere, 2).Value = dictCount(agentKey)
            wsRaport.Cells(randScriere, 3).Value = dictAgenti(agentKey)
            wsRaport.Cells(randScriere, 3).NumberFormat = "#,##0.00 lei"
            randScriere = randScriere + 1
        Next agentKey
        
        ' Total
        wsRaport.Cells(randScriere, 1).Value = "TOTAL"
        wsRaport.Cells(randScriere, 1).Font.Bold = True
        wsRaport.Cells(randScriere, 3).Formula = "=SUM(C4:C" & randScriere - 1 & ")"
        wsRaport.Cells(randScriere, 3).Font.Bold = True
        
        ' Formatare tabel
        wsRaport.Range("A3:C" & randScriere).Borders.LineStyle = xlContinuous
        wsRaport.Columns("A:C").AutoFit
    Next lunii
    
    ' Restaurăm setările
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    
    MsgBox "Rapoarte generate: " & dictLuni.Count & " luni.", vbInformation
End Sub

Trimiterea automată de emailuri din Excel (Outlook)

Sub TrimiteRaportPeEmail()
    Dim outlook As Object
    Dim mail As Object
    Dim ws As Worksheet
    
    Set ws = ThisWorkbook.Sheets("Stoc_Curent")
    
    ' Verifică dacă există produse sub stoc minim
    Dim nrAlerte As Long
    nrAlerte = WorksheetFunction.CountIf(ws.Columns(5), "REAPROVIZIONARE URGENTĂ")
    
    If nrAlerte = 0 Then
        MsgBox "Nu sunt alerte de reaprovizionare."
        Exit Sub
    End If
    
    ' Salvează foaia ca PDF
    Dim caleaPDF As String
    caleaPDF = Environ("TEMP") & "\Alerte_Stoc_" & Format(Now, "YYYY-MM-DD") & ".pdf"
    ws.ExportAsFixedFormat xlTypePDF, caleaPDF
    
    ' Creează emailul în Outlook
    Set outlook = CreateObject("Outlook.Application")
    Set mail = outlook.CreateItem(0)
    
    With mail
        .To = "achizitii@firma.ro"
        .CC = "director@firma.ro"
        .Subject = "ALERTĂ: " & nrAlerte & " produse necesită reaprovizionare - " & Format(Now, "DD.MM.YYYY")
        .Body = "Bună ziua," & vbCrLf & vbCrLf & _
                "Sistemul automat de monitorizare stocuri a detectat " & nrAlerte & _
                " produse cu stoc sub nivelul minim." & vbCrLf & vbCrLf & _
                "Lista detaliată este atașată în PDF." & vbCrLf & vbCrLf & _
                "Excel Group Stoc Monitor"
        .Attachments.Add caleaPDF
        .Display  ' sau .Send pentru trimitere directă
    End With
End Sub

Gestionarea erorilor: codul profesionist

Sub ProceduraRobusta()
    On Error GoTo GestionareEroare
    
    ' codul tău aici
    
    GoTo Sfarsit

GestionareEroare:
    Dim mesaj As String
    mesaj = "Eroare " & Err.Number & ": " & Err.Description & vbCrLf & _
            "Linia: " & Erl & vbCrLf & _
            "Procedura: ProceduraRobusta"
    
    ' Loghezi eroarea într-o foaie sau fișier
    LogEroare mesaj
    
    MsgBox mesaj, vbCritical, "Eroare"
    Resume Sfarsit

Sfarsit:
    ' Cleanup: restaurezi întotdeauna setările
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
End Sub

Sub LogEroare(mesaj As String)
    Dim wsLog As Worksheet
    Set wsLog = GetOrCreateSheet(ThisWorkbook, "Log_Erori")
    Dim rnd As Long
    rnd = LastRow(wsLog) + 1
    wsLog.Cells(rnd, 1).Value = Now
    wsLog.Cells(rnd, 2).Value = mesaj
End Sub

Concluzie

VBA avansat transformă Excel dintr-un instrument de calcul într-un sistem de automatizare complet. Cu 100-200 de linii de cod bine scrise, automatizezi munci care durau ore — și o faci corect, de fiecare dată.

La Excel Group scriem și implementăm soluții VBA pentru firme din România și Moldova — de la rapoarte automate la sisteme complete de procesare date. Contactează-ne.


Întrebări frecvente

VBA mai e relevant în 2026, cu Office Scripts și Python în Excel?

Da — VBA rămâne cel mai complet instrument pentru automatizare Excel locală, integrare cu aplicații Windows (Outlook, Word, Access) și compatibilitate cu versiuni vechi. Office Scripts e mai bun pentru automatizare cloud/SharePoint.

Codul VBA se poate proteja de vizualizare?

Da — din VBA Editor: Tools → VBAProject Properties → Protection → Lock project for viewing + parolă. Nu e criptare militară, dar descurajează modificările accidentale.

Pot apela API-uri externe din VBA?

Da — cu obiectul XMLHTTP sau WinHttp.WinHttpRequest. Poți face GET/POST la orice API REST și procesa răspunsul JSON (manual cu funcții de parsing sau cu un parser JSON VBA open-source).

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *