Malicious Office (OOXML) / .XLSM — malware analysis report

Static analysis result for SHA-256 d5c9b643b5c7e4f1…

MALICIOUS

Office (OOXML) / .XLSM

1.24 MB Created: 2015-06-05 18:19:34 UTC Authoring application: Microsoft Excel 16.0300 First seen: 2026-06-24
MD5: 986f66510d4e0701f47d0c3b35d705e2 SHA-1: 924f979eab2ae7329fe03edcb5bf7914919ade7c SHA-256: d5c9b643b5c7e4f1ca90f8f6ccaeb24f681441ce9fecbe5154416ad661143b2e
162 Risk Score

Heuristics 5

  • VBA project inside OOXML medium 3 related findings OOXML_VBA
    Document contains a VBA project — VBA macros present
  • VBA macro-virus self-replication / AV tampering critical OLE_VBA_MACRO_VIRUS_REPLICATION
    VBA macro programmatically rewrites VBA project code through the VBE object model (CodeModule/VBComponents InsertLines/DeleteLines/AddFromString or OrganizerCopy) to copy itself into the global template and other open documents, and/or disables Office macro-virus protection (Options.VirusProtection = False). This is the defining behavior of the W97M document macro-virus family — self-replicating code with no benign document use, independent of any AV signature.
    Matched line in script
        codeMod.AddFromString ObtenerCodigoFormulario()
  • CreateObject call high OLE_VBA_CREATEOBJ
    CreateObject call
    Matched line in script
        Set colMap = CreateObject("Scripting.Dictionary")
  • CallByName call high OLE_VBA_CALLBYNAME
    CallByName call
    Matched line in script
            CallByName obj, nombreProp, VbLet, valor
  • Embedded URL info EMBEDDED_URL
    One or more URLs were extracted from the document. The URL itself is not a detection — see the per-URL labels for which channel (macro, JS, link annotation, document body, ...) reached each URL.
    URL http://schemas.microsoft.com/office/2006/01/customui In document text (OOXML body / shared strings)
    • http://schemas.microsoft.com/office/2009/07/customuiIn document text (OOXML body / shared strings)

Extracted artifacts 2

Files carved from inside the sample during analysis.

FilenameKindSourceSize
macros.bas vba-macro oletools.olevba.extract_macros (decoded VBA source from OOXML) 87352 bytes
SHA-256: 52b0146779fc7aa96273e1f8ee1bfec0ce050a15a798588685434eeff17ed297
Preview script
First 1,000 lines of the extracted script
Attribute VB_Name = "ThisWorkbook"
Attribute VB_Base = "0{00020819-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja70"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja69"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja1"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja3"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit

Private Sub Worksheet_Activate()
    ValidarHojasPorID
End Sub

Private Sub Worksheet_Change(ByVal Target As Range)
    
    Dim tbl As ListObject
    Dim rangoID As Range
    
    On Error GoTo Salida
    
    Set tbl = Me.ListObjects("list_items")
    Set rangoID = tbl.ListColumns("ID").DataBodyRange

    ' Validar solo si el cambio fue en la columna ID
    If Not Intersect(Target, rangoID) Is Nothing Then
        
        Application.EnableEvents = False
        
        Dim celda As Range
        Dim id As String
        
        For Each celda In Intersect(Target, rangoID)
            
            id = Trim(celda.Value)
            
            If id <> "" Then
                If HojaExiste(id) Then
                    celda.Font.Color = RGB(0, 0, 0)
                Else
                    celda.Font.Color = RGB(255, 0, 0)
                End If
            End If
            
        Next celda
        
    End If

Salida:
    Application.EnableEvents = True

End Sub


Sub ValidarHojasPorID()

    Dim tbl As ListObject
    Dim celda As Range
    Dim id As String
    
    Set tbl = Me.ListObjects("list_items")
    
    For Each celda In tbl.ListColumns("ID").DataBodyRange
        
        id = Trim(celda.Value)
        
        If id <> "" Then
            If HojaExiste(id) Then
                celda.Font.Color = RGB(0, 0, 0)
            Else
                celda.Font.Color = RGB(255, 0, 0)
            End If
        End If
        
    Next celda

End Sub


Function HojaExiste(nombreHoja As String) As Boolean
    
    Dim ws As Worksheet
    HojaExiste = False
    
    For Each ws In ThisWorkbook.Worksheets
        If ws.Name = nombreHoja Then
            HojaExiste = True
            Exit Function
        End If
    Next ws

End Function

Attribute VB_Name = "Hoja77"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True

Attribute VB_Name = "Hoja7"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja23"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja8"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja5"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja27"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja28"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja29"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja30"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja34"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja35"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja36"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja71"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "mod_load_ribbon"
Sub Ribbon_Load(ribbonUI As IRibbonUI)
    Set ribbon = ribbonUI
End Sub



Attribute VB_Name = "Hoja37"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja38"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja39"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja40"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja41"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja42"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja32"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja43"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja33"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja13"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "clsEventosForm"
Attribute VB_Base = "0{FCFB3D2A-A0FA-1068-A738-08002B3371B5}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = False
Option Explicit

Public WithEvents btnBuscar As MSForms.CommandButton
Attribute btnBuscar.VB_VarHelpID = -1
Public WithEvents lstResultados As MSForms.ListBox
Attribute lstResultados.VB_VarHelpID = -1

Public cmbColumna As MSForms.ComboBox
Public txtTermino As MSForms.TextBox

Public datos As Variant
Public headers As Variant

Private Sub btnBuscar_Click()

    Dim i As Long, j As Long
    Dim termino As String
    Dim colIndex As Long
    
    If cmbColumna.ListIndex = -1 Then
        MsgBox "Seleccione una columna"
        Exit Sub
    End If
    
    termino = LCase(txtTermino.Text)
    colIndex = cmbColumna.ListIndex + 1
    
    lstResultados.Clear
    lstResultados.ColumnCount = UBound(datos, 2)
    
    For i = 1 To UBound(datos, 1)
        
        If Not IsEmpty(datos(i, colIndex)) Then
            
            If InStr(1, LCase(datos(i, colIndex)), termino) > 0 Then
                
                lstResultados.AddItem
                
                For j = 1 To UBound(datos, 2)
                    lstResultados.List(lstResultados.ListCount - 1, j - 1) = datos(i, j)
                Next j
                
            End If
            
        End If
        
    Next i

End Sub

Private Sub lstResultados_Click()

    Dim colMap As Object
    Set colMap = CreateObject("Scripting.Dictionary")
    
    ' ?? CONFIGURA TU MAPEO AQUÍ
    colMap.Add "ID", "A1"
    colMap.Add "NOMBRE", "B1"
    colMap.Add "VALOR", "C1"
    colMap.Add "UNIDAD", "D1"
    
    Dim i As Long
    Dim colName As String
    Dim colIndex As Long
    
    If lstResultados.ListIndex = -1 Then Exit Sub
    
    For i = 1 To UBound(headers, 2)
        
        colName = headers(1, i)
        
        If colMap.Exists(colName) Then
            
            colIndex = i - 1
            
            ActiveSheet.Range(colMap(colName)).Value = _
                lstResultados.List(lstResultados.ListIndex, colIndex)
                
        End If
        
    Next i

End Sub


Attribute VB_Name = "Hoja14"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "mod_genera_formulario"
'==============================================================
' MÓDULO: modGeneradorForm
' Genera frmNuevoInsumo completo (controles + código) por VBIDE
' Requisito: Confiar en el acceso al modelo de objetos de
' proyectos VBA (Archivo > Opciones > Centro de confianza)
'==============================================================
Option Explicit

Sub GenerarFormularioNuevoInsumo()

    Dim vbProj As Object
    Dim vbComp As Object
    Dim frm As Object
    Dim codeMod As Object
    Dim nombreGenerado As String

    On Error GoTo ErrorHandler

    Set vbProj = ThisWorkbook.VBProject

    '--- Si ya existe un formulario con ese nombre, lo elimina primero ---
    Dim comp As Object
    For Each comp In vbProj.VBComponents
        If comp.Name = "frmNuevoInsumo" Then
            vbProj.VBComponents.Remove comp
            Exit For
        End If
    Next comp

    '--- Crea el UserForm nuevo ---
    Set vbComp = vbProj.VBComponents.Add(3) ' 3 = vbext_ct_MSForm
    nombreGenerado = vbComp.Name

    DoEvents
    DoEvents ' doble ciclo para asegurar que el IDE termine de inicializar el Designer

    Set frm = vbComp.Designer

    '--- Tamaño y título con reintento silencioso ---
    EstablecerPropiedad frm, "Width", 330
    EstablecerPropiedad frm, "Height", 310
    EstablecerPropiedad frm, "Caption", "Buscador de Insumos"

    '=== Etiquetas (Labels) ===
    AgregarLabel frm, "lblProveedor", "Proveedor", 12, 12, 130, 14
    AgregarLabel frm, "lblInsumo", "Insumo", 12, 168, 140, 14
    AgregarLabel frm, "lblGrupo", "Grupo", 56, 12, 130, 14
    AgregarLabel frm, "lblSubgrupo", "Sub Grupo", 56, 168, 140, 14
    AgregarLabel frm, "lblUnidad", "Unidad", 100, 12, 130, 14
    AgregarLabel frm, "lblValor", "Valor", 100, 168, 140, 14

    '=== ComboBox / TextBox ===
    AgregarControl frm, "cmbProveedor", "Forms.ComboBox.1", 28, 12, 130, 18
    AgregarControl frm, "txtInsumo", "Forms.TextBox.1", 28, 168, 140, 18
    AgregarControl frm, "cmbGrupo", "Forms.ComboBox.1", 72, 12, 130, 18
    AgregarControl frm, "cmbSubgrupo", "Forms.ComboBox.1", 72, 168, 140, 18
    AgregarControl frm, "cmbUnidad", "Forms.ComboBox.1", 116, 12, 130, 18
    AgregarControl frm, "txtValor", "Forms.TextBox.1", 116, 168, 140, 18

    '=== Botón Validar (ancho completo) ===
    Dim btnValidar As Object
    Set btnValidar = AgregarControl(frm, "btnValidar", "Forms.CommandButton.1", 146, 12, 296, 26)
    EstablecerPropiedad btnValidar, "Caption", "Validar"

    '=== Frame "Vista Previa" ===
    Dim fra As Object
    Set fra = frm.Controls.Add("Forms.Frame.1", "fraPreview", True)
    EstablecerPropiedad fra, "Caption", "Vista Previa"
    EstablecerPropiedad fra, "Top", 180
    EstablecerPropiedad fra, "Left", 12
    EstablecerPropiedad fra, "Width", 296
    EstablecerPropiedad fra, "Height", 60

    Dim lblPrev As Object
    Set lblPrev = fra.Controls.Add("Forms.Label.1", "lblPreview", True)
    EstablecerPropiedad lblPrev, "Caption", "(proveedor)  ·  (insumo)  ·  (grupo)  ·  (unidad)  ·  (valor pendiente)"
    EstablecerPropiedad lblPrev, "Top", 12
    EstablecerPropiedad lblPrev, "Left", 8
    EstablecerPropiedad lblPrev, "Width", 276
    EstablecerPropiedad lblPrev, "Height", 36
    EstablecerPropiedad lblPrev, "WordWrap", True

    '=== Botones inferiores ===
    Dim btnGuardar As Object, btnLimpiar As Object, btnCerrar As Object
    Set btnGuardar = AgregarControl(frm, "btnGuardar", "Forms.CommandButton.1", 250, 12, 94, 26)
    EstablecerPropiedad btnGuardar, "Caption", "Guardar"

    Set btnLimpiar = AgregarControl(frm, "btnLimpiar", "Forms.CommandButton.1", 250, 114, 94, 26)
    EstablecerPropiedad btnLimpiar, "Caption", "Limpiar"

    Set btnCerrar = AgregarControl(frm, "btnCerrar", "Forms.CommandButton.1", 250, 214, 94, 26)
    EstablecerPropiedad btnCerrar, "Caption", "Cerrar"

    '--- Inyecta el código del formulario ---
    Set codeMod = vbComp.CodeModule
    codeMod.AddFromString ObtenerCodigoFormulario()

    MsgBox "Formulario generado con todos sus controles." & vbCrLf & vbCrLf & _
           "Quedó con el nombre temporal: " & nombreGenerado & vbCrLf & vbCrLf & _
           "Ahora renómbralo manualmente a 'frmNuevoInsumo':" & vbCrLf & _
           "1. Selecciónalo en el Explorador de proyectos" & vbCrLf & _
           "2. Presiona F4 (ventana Propiedades)" & vbCrLf & _
           "3. Cambia la propiedad (Name) a frmNuevoInsumo", _
           vbInformation, "Casi listo"
    Exit Sub

ErrorHandler:
    MsgBox "Error al generar el formulario: " & Err.Description & vbCrLf & _
           "(línea aproximada según el último paso ejecutado)", vbCritical, "Error"
End Sub

'--------------------------------------------------------------
' Asigna una propiedad con reintento silencioso (hasta 5 intentos
' con una pequeña espera), para absorber inicializaciones tardías
' del objeto COM del Designer/Control recién creado.
'--------------------------------------------------------------
Private Sub EstablecerPropiedad(ByVal obj As Object, ByVal nombreProp As String, ByVal valor As Variant)
    Dim intentos As Integer
    Dim exito As Boolean
    exito = False

    For intentos = 1 To 5
        On Error Resume Next
        Err.Clear
        CallByName obj, nombreProp, VbLet, valor
        If Err.Number = 0 Then
            exito = True
            On Error GoTo 0
            Exit Sub
        End If
        On Error GoTo 0
        DoEvents
    Next intentos

    If Not exito Then
        ' Si tras 5 intentos sigue sin poder, lo deja pasar sin tumbar todo
        Debug.Print "No se pudo establecer " & nombreProp & " = " & valor
    End If
End Sub

'--------------------------------------------------------------
' Crea un Label dentro del formulario
'--------------------------------------------------------------
Private Sub AgregarLabel(ByVal frm As Object, ByVal sNombre As String, _
                          ByVal sCaption As String, ByVal nTop As Single, _
                          ByVal nLeft As Single, ByVal nWidth As Single, _
                          ByVal nHeight As Single)
    Dim lbl As Object
    Set lbl = frm.Controls.Add("Forms.Label.1", sNombre, True)
    lbl.Caption = sCaption
    lbl.Top = nTop
    lbl.Left = nLeft
    lbl.Width = nWidth
    lbl.Height = nHeight
End Sub

'--------------------------------------------------------------
' Crea un control genérico (ComboBox, TextBox, CommandButton)
' Devuelve la referencia para personalizar Caption u otras props
'--------------------------------------------------------------
Private Function AgregarControl(ByVal frm As Object, ByVal sNombre As String, _
                                  ByVal sProgID As String, ByVal nTop As Single, _
                                  ByVal nLeft As Single, ByVal nWidth As Single, _
                                  ByVal nHeight As Single) As Object
    Dim ctl As Object
    Set ctl = frm.Controls.Add(sProgID, sNombre, True)
    ctl.Top = nTop
    ctl.Left = nLeft
    ctl.Width = nWidth
    ctl.Height = nHeight
    Set AgregarControl = ctl
End Function

'--------------------------------------------------------------
' Devuelve el código completo a inyectar en el formulario
'--------------------------------------------------------------
Private Function ObtenerCodigoFormulario() As String
    Dim s As String

    s = "Private Sub UserForm_Initialize()" & vbCrLf
    s = s & "    Me.Caption = ""Nuevo insumo""" & vbCrLf
    s = s & "    CargarProveedores cmbProveedor" & vbCrLf
    s = s & "    CargarGrupos cmbGrupo" & vbCrLf
    s = s & "    CargarUnidades cmbUnidad" & vbCrLf
    s = s & "    cmbSubgrupo.Clear" & vbCrLf
    s = s & "    cmbSubgrupo.Enabled = False" & vbCrLf
    s = s & "    LimpiarPreview" & vbCrLf
    s = s & "End Sub" & vbCrLf & vbCrLf

    s = s & "Private Sub cmbGrupo_Change()" & vbCrLf
    s = s & "    CargarSubgruposPorGrupo cmbSubgrupo, cmbGrupo.Value" & vbCrLf
    s = s & "    cmbSubgrupo.Enabled = (cmbGrupo.Value <> """")" & vbCrLf
    s = s & "    ActualizarPreview" & vbCrLf
    s = s & "End Sub" & vbCrLf & vbCrLf

    s = s & "Private Sub cmbProveedor_Change(): ActualizarPreview: End Sub" & vbCrLf
    s = s & "Private Sub txtInsumo_Change(): ActualizarPreview: End Sub" & vbCrLf
    s = s & "Private Sub cmbSubgrupo_Change(): ActualizarPreview: End Sub" & vbCrLf
    s = s & "Private Sub cmbUnidad_Change(): ActualizarPreview: End Sub" & vbCrLf
    s = s & "Private Sub txtValor_Change(): ActualizarPreview: End Sub" & vbCrLf & vbCrLf

    s = s & "Private Sub ActualizarPreview()" & vbCrLf
    s = s & "    Dim sValor As String" & vbCrLf
    s = s & "    If IsNumeric(txtValor.Value) Then" & vbCrLf
    s = s & "        sValor = Format(CDbl(txtValor.Value), ""$ #,##0.00"")" & vbCrLf
    s = s & "    Else" & vbCrLf
    s = s & "        sValor = ""(valor pendiente)""" & vbCrLf
    s = s & "    End If" & vbCrLf
    s = s & "    lblPreview.Caption = _" & vbCrLf
    s = s & "        IIf(cmbProveedor.Value = """", ""(proveedor)"", cmbProveedor.Value) & ""  ·  "" & _" & vbCrLf
    s = s & "        IIf(txtInsumo.Value = """", ""(insumo)"", txtInsumo.Value) & ""  ·  "" & _" & vbCrLf
    s = s & "        IIf(cmbGrupo.Value = """", ""(grupo)"", cmbGrupo.Value) & _" & vbCrLf
    s = s & "        IIf(cmbSubgrupo.Value <> """", "" / "" & cmbSubgrupo.Value, """") & ""  ·  "" & _" & vbCrLf
    s = s & "        IIf(cmbUnidad.Value = """", ""(unidad)"", cmbUnidad.Value) & ""  ·  "" & sValor" & vbCrLf
    s = s & "End Sub" & vbCrLf & vbCrLf

    s = s & "Private Sub LimpiarPreview()" & vbCrLf
    s = s & "    lblPreview.Caption = ""(proveedor)  ·  (insumo)  ·  (grupo)  ·  (unidad)  ·  (valor pendiente)""" & vbCrLf
    s = s & "End Sub" & vbCrLf & vbCrLf

    s = s & "Private Sub btnValidar_Click()" & vbCrLf
    s = s & "    If Trim(txtInsumo.Value) = """" Then" & vbCrLf
    s = s & "        MsgBox ""Ingrese el nombre del insumo a validar."", vbExclamation" & vbCrLf
    s = s & "        Exit Sub" & vbCrLf
    s = s & "    End If" & vbCrLf
    s = s & "    If ExisteInsumo(txtInsumo.Value, cmbProveedor.Value) Then" & vbCrLf
    s = s & "        MsgBox ""El insumo ya existe para este proveedor."", vbInformation, ""Insumo encontrado""" & vbCrLf
    s = s & "    Else" & vbCrLf
    s = s & "        MsgBox ""El insumo no existe. Puede continuar."", vbInformation, ""Insumo disponible""" & vbCrLf
    s = s & "    End If" & vbCrLf
    s = s & "End Sub" & vbCrLf & vbCrLf

    s = s & "Private Sub btnGuardar_Click()" & vbCrLf
    s = s & "    Dim valorNumerico As Double" & vbCrLf
    s = s & "    If Not IsNumeric(txtValor.Value) Then" & vbCrLf
    s = s & "        MsgBox ""El valor debe ser numérico."", vbExclamation" & vbCrLf
    s = s & "        Exit Sub" & vbCrLf
    s = s & "    End If" & vbCrLf
    s = s & "    valorNumerico = CDbl(txtValor.Value)" & vbCrLf
    s = s & "    If AgregarInsumo(cmbProveedor.Value, txtInsumo.Value, cmbGrupo.Value, _" & vbCrLf
    s = s & "                      cmbSubgrupo.Value, cmbUnidad.Value, valorNumerico) Then" & vbCrLf
    s = s & "        Dim respuesta As VbMsgBoxResult" & vbCrLf
    s = s & "        respuesta = MsgBox(""Insumo agregado correctamente."" & vbCrLf & vbCrLf & _" & vbCrLf
    s = s & "                            ""¿Desea agregar otro insumo?"", _" & vbCrLf
    s = s & "                            vbQuestion + vbYesNo, ""Éxito"")" & vbCrLf
    s = s & "        If respuesta = vbYes Then" & vbCrLf
    s = s & "            btnLimpiar_Click" & vbCrLf
    s = s & "            cmbProveedor.SetFocus" & vbCrLf
    s = s & "        Else" & vbCrLf
    s = s & "            Unload Me" & vbCrLf
    s = s & "        End If" & vbCrLf
    s = s & "    End If" & vbCrLf
    s = s & "End Sub" & vbCrLf & vbCrLf

    s = s & "Private Sub btnLimpiar_Click()" & vbCrLf
    s = s & "    cmbProveedor.Value = """"" & vbCrLf
    s = s & "    txtInsumo.Value = """"" & vbCrLf
    s = s & "    cmbGrupo.Value = """"" & vbCrLf
    s = s & "    cmbSubgrupo.Clear" & vbCrLf
    s = s & "    cmbSubgrupo.Enabled = False" & vbCrLf
    s = s & "    cmbUnidad.Value = """"" & vbCrLf
    s = s & "    txtValor.Value = """"" & vbCrLf
    s = s & "    LimpiarPreview" & vbCrLf
    s = s & "    txtInsumo.SetFocus" & vbCrLf
    s = s & "End Sub" & vbCrLf & vbCrLf

    s = s & "Private Sub btnCerrar_Click()" & vbCrLf
    s = s & "    Unload Me" & vbCrLf
    s = s & "End Sub" & vbCrLf

    ObtenerCodigoFormulario = s
End Function


Attribute VB_Name = "Hoja26"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja31"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja44"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja45"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja46"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja47"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja48"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja49"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja9"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja10"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja11"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja12"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja50"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja15"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja74"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "mod_ia"
Option Explicit

Sub CopiarPromptAPU(control As IRibbonControl)

    MsgBox "Futura funcionalidad para consultas con IA"

End Sub



Attribute VB_Name = "Hoja17"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja20"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja18"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja21"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit


Attribute VB_Name = "Hoja22"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
…
vbaProject_00.bin vba-project OOXML VBA project: xl/vbaProject.bin 380928 bytes
SHA-256: c9e62a7d62a44b2ac5faadde9a59feeac87d8ca3f443111ee171ea2a533edbf1