MALICIOUS
350
Risk Score
Malware Insights
MITRE ATT&CK
T1059.005 Visual Basic
T1105 Ingress Tool Transfer
T1204.002 Malicious File
The sample contains a Workbook_Open macro that utilizes WScript.Shell and CreateObject to download and execute a second-stage payload. The macro's obfuscated nature and use of URLDownloadToFile strongly suggest a downloader functionality. The embedded URLs, while many are benign, are referenced by the macro, indicating potential C2 communication or payload staging.
Heuristics 9
-
VBA project inside OOXML medium 7 related findings OOXML_VBADocument contains a VBA project — VBA macros present
-
Potential Shell call in VBA critical OLE_VBA_SHELLPotential Shell call in VBAMatched line in script
Dim hWndEx As Long 'ID of Interface Dim sShellCmd As String 'Shell Command Dim DataLocal As String, SA, SS, DD -
WScript.Shell usage critical OLE_VBA_WSCRIPTWScript.Shell usageMatched line in script
'=== Узнаём пользовательскую директорию Set WSHShell = CreateObject("WScript.Shell") DataLocal = WSHShell.specialfolders("AppData") -
URLDownloadToFile in VBA critical OLE_VBA_DOWNLOADURLDownloadToFile in VBAMatched line in script
'объявление функции API - URLDownloadToFile ' работает на любых ПК под управлением ОС Windows -
Obfuscated auto-exec VBA loader critical OLE_VBA_OBFUSCATED_AUTOEXEC_LOADERAuto-exec VBA reconstructs strings with a heavy custom decoder (numeric char-array, repeated hex-string decode, or junk-token Replace removal) and feeds them to a COM-instantiation or execution sink. This obfuscated-loader shape keeps CreateObject/Shell/URL indicators out of the macro source.Matched line in script
#Else Set pDictionary = CreateObject("Scripting.Dictionary") #End If -
CreateObject call high OLE_VBA_CREATEOBJCreateObject callMatched line in script
#Else Set pDictionary = CreateObject("Scripting.Dictionary") #End If -
VBA p-code auto-exec with execution tokens high OLE_VBA_PCODE_AUTOEXEC_EXECCompiled VBA/cache stream contains an auto-execution token together with shell/download/object-execution tokens. This catches p-code-only or source-extraction-failure macro documents where visible source is unavailable.
-
Workbook_Open macro low OLE_VBA_WBOPENWorkbook_Open macroMatched line in script
Attribute VB_Customizable = True Private Sub Workbook_Open() Application.OnKey "^{LEFT}", "SetPodbor" -
Embedded URL info EMBEDDED_URLOne 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 https://github.com/timhall/VBA-Dictionary\r\nAuthor Referenced by macro
- https://github.com/timhall/VBA-DictionaryReferenced by macro
- https://github.com/VBA-tools/VBA-JSONReferenced by macro
- http://www.vbaccelerator.com/home/VB/Code/Techniques/RunTime_Debug_Tracing/VB6_Tracer_Utility_zip_cStringBuilder_cls.aspReferenced by macro
- https://github.com/VBA-tools/VBA-JSON/pull/82Referenced by macro
- https://github.com/VBA-tools/VBA-UtcConverterReferenced by macro
- http://www.onicos.com/staff/iz/formats/gzip.htmlReferenced by macro
- https://direct.istochnik.ru/istapi/1.0.0/contragents/prices?api_key=#APIKEY#&format=xlApp&fields=2Referenced by macro
- https://direct.istochnik.ru/istapi/1.0.0/contragents/prices?api_key=#APIKEY#&format=xlAppJson&fields=2Referenced by macro
- https://www.#BRAND#.ru/product/#TID#Referenced by macro
- https://www.istochnik.ru/soft/excelClient.xmlReferenced by macro
- https://direct.istochnik.ru/istapi/1.0.0/contragents/prices?api_key=#APIKEY#&format=xlApp&fields=2�Referenced by macro
- https://direct.istochnik.ru/istapi/1.0.0/contragents/prices?api_key=#APIKEY#&format=xlAppJson&fields=2�Referenced by macro
- https://www.#BRAND#.ru/product/#TID#�Referenced by macro
- https://www.istochnik.ru/soft/excelClient.xml�+Referenced by macro
- http://www.opensource.org/licenses/mit-license.php)\r\nReferenced by macro
- http://www.opensource.org/licenses/mit-license.phpReferenced by macro
- http://msdn.microsoft.com/en-us/library/office/gg278481(v=office.15).aspxReferenced by macro
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms724421.aspxReferenced by macro
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms724949.aspxReferenced by macro
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms725485.aspxReferenced by macro
- http://support.microsoft.com/kb/269370Referenced by macro
- http://www.ietf.org/rfc/rfc4627.txtReferenced by macro
- https://support.microsoft.com/en-us/kb/272138Referenced by macro
- https://tools.ietf.org/html/rfc1952#section-2.3Referenced by macro
- http://robiton3.1gb.ru/soft/excelClient.xmlReferenced by macro
- http://www.opensource.org/licenses/mit-license.php�Referenced by macro
- http://msdn.microsoft.com/en-us/library/office/gg278481(v=office.15).aspx�Referenced by macro
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms724421.aspx�Referenced by macro
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms724949.aspx�����Referenced by macro
- http://msdn.microsoft.com/en-us/library/windows/desktop/ms725485.aspx�Referenced by macro
- http://www.opensource.org/licenses/mit-license.php)�Referenced by macro
Extracted artifacts 2
Files carved from inside the sample during analysis.
| Filename | Kind | Source | Size |
|---|---|---|---|
macros.bas |
vba-macro | oletools.olevba.extract_macros (decoded VBA source from OOXML) | 227434 bytes |
SHA-256: 34941baf1b8db1f615ee876f5f3c1c8dc4977af3744e321d6ee10357200bef99 |
|||
Preview scriptFirst 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
Private Sub Workbook_Open()
Application.OnKey "^{LEFT}", "SetPodbor"
Application.OnKey "^{RIGHT}", "SetFind"
Application.OnKey "^{UP}", "SetFindPrev"
Application.OnKey "^{DOWN}", "SetFindNext"
MyVer_Check False
GetNeedUpdate
End Sub
Attribute VB_Name = "Price"
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
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Cancel = True
SetPodbor Target.Row
End Sub
Attribute VB_Name = "Hide"
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 = "Dictionary"
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
Attribute VB_Description = "Drop-in replacement for Scripting.Dictionary on Mac\r\n\r\nDictionary v1.4.0\r\n(c) Tim Hall - https://github.com/timhall/VBA-Dictionary\r\nAuthor: tim.hall.engr@gmail.com\r\nLicense: MIT (http://www.opensource.org/licenses/mit-license.php)\r\n"
''
' Dictionary v1.4.1
' (c) Tim Hall - https://github.com/timhall/VBA-Dictionary
'
' Drop-in replacement for Scripting.Dictionary on Mac
'
' @author: tim.hall.engr@gmail.com
' @license: MIT (http://www.opensource.org/licenses/mit-license.php
'
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ '
Option Explicit
' --------------------------------------------- '
' Constants and Private Variables
' --------------------------------------------- '
#Const UseScriptingDictionaryIfAvailable = False
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
' KeyValue 0: FormattedKey, 1: OriginalKey, 2: Value
Private pKeyValues As Collection
Private pKeys() As Variant
Private pItems() As Variant
Private pObjectKeys As Collection
Private pCompareMode As CompareMethod
#Else
Private pDictionary As Object
#End If
' --------------------------------------------- '
' Types
' --------------------------------------------- '
Public Enum CompareMethod
BinaryCompare = VBA.vbBinaryCompare
TextCompare = VBA.vbTextCompare
DatabaseCompare = VBA.vbDatabaseCompare
End Enum
' --------------------------------------------- '
' Properties
' --------------------------------------------- '
Public Property Get CompareMode() As CompareMethod
Attribute CompareMode.VB_Description = "Set or get the string comparison method."
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
CompareMode = pCompareMode
#Else
CompareMode = pDictionary.CompareMode
#End If
End Property
Public Property Let CompareMode(value As CompareMethod)
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
If Me.Count > 0 Then
' Can't change CompareMode for Dictionary that contains data
' http://msdn.microsoft.com/en-us/library/office/gg278481(v=office.15).aspx
Err.Raise 5 ' Invalid procedure call or argument
End If
pCompareMode = value
#Else
pDictionary.CompareMode = value
#End If
End Property
Public Property Get Count() As Long
Attribute Count.VB_Description = "Get the number of items in the dictionary.\n"
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
Count = pKeyValues.Count
#Else
Count = pDictionary.Count
#End If
End Property
Public Property Get Item(key As Variant) As Variant
Attribute Item.VB_Description = "Set or get the item for a given key."
Attribute Item.VB_UserMemId = 0
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
Dim KeyValue As Variant
KeyValue = GetKeyValue(key)
If Not IsEmpty(KeyValue) Then
If VBA.IsObject(KeyValue(2)) Then
Set Item = KeyValue(2)
Else
Item = KeyValue(2)
End If
Else
' Not found -> Returns Empty
End If
#Else
If VBA.IsObject(pDictionary.Item(key)) Then
Set Item = pDictionary.Item(key)
Else
Item = pDictionary.Item(key)
End If
#End If
End Property
Public Property Let Item(key As Variant, value As Variant)
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
If Me.Exists(key) Then
ReplaceKeyValue GetKeyValue(key), key, value
Else
AddKeyValue key, value
End If
#Else
pDictionary.Item(key) = value
#End If
End Property
Public Property Set Item(key As Variant, value As Variant)
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
If Me.Exists(key) Then
ReplaceKeyValue GetKeyValue(key), key, value
Else
AddKeyValue key, value
End If
#Else
Set pDictionary.Item(key) = value
#End If
End Property
Public Property Let key(Previous As Variant, Updated As Variant)
Attribute key.VB_Description = "Change a key to a different key."
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
Dim KeyValue As Variant
KeyValue = GetKeyValue(Previous)
If Not VBA.IsEmpty(KeyValue) Then
ReplaceKeyValue KeyValue, Updated, KeyValue(2)
End If
#Else
pDictionary.key(Previous) = Updated
#End If
End Property
' ============================================= '
' Public Methods
' ============================================= '
''
' Add an item with the given key
'
' @param {Variant} Key
' @param {Variant} Item
' --------------------------------------------- '
Public Sub Add(key As Variant, Item As Variant)
Attribute Add.VB_Description = "Add a new key and item to the dictionary."
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
If Not Me.Exists(key) Then
AddKeyValue key, Item
Else
' This key is already associated with an element of this collection
Err.Raise 457
End If
#Else
pDictionary.Add key, Item
#End If
End Sub
''
' Check if an item exists for the given key
'
' @param {Variant} Key
' @return {Boolean}
' --------------------------------------------- '
Public Function Exists(key As Variant) As Boolean
Attribute Exists.VB_Description = "Determine if a given key is in the dictionary."
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
Exists = Not IsEmpty(GetKeyValue(key))
#Else
Exists = pDictionary.Exists(key)
#End If
End Function
''
' Get an array of all items
'
' @return {Variant}
' --------------------------------------------- '
Public Function Items() As Variant
Attribute Items.VB_Description = "Get an array containing all items in the dictionary."
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
If Me.Count > 0 Then
Items = pItems
Else
' Split("") creates initialized empty array that matches Dictionary Keys and Items
Items = VBA.Split("")
End If
#Else
Items = pDictionary.Items
#End If
End Function
''
' Get an array of all keys
'
' @return {Variant}
' --------------------------------------------- '
Public Function Keys() As Variant
Attribute Keys.VB_Description = "Get an array containing all keys in the dictionary."
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
If Me.Count > 0 Then
Keys = pKeys
Else
' Split("") creates initialized empty array that matches Dictionary Keys and Items
Keys = VBA.Split("")
End If
#Else
Keys = pDictionary.Keys
#End If
End Function
''
' Remove an item for the given key
'
' @param {Variant} Key
' --------------------------------------------- '
Public Sub Remove(key As Variant)
Attribute Remove.VB_Description = "Remove a given key from the dictionary."
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
Dim KeyValue As Variant
KeyValue = GetKeyValue(key)
If Not VBA.IsEmpty(KeyValue) Then
RemoveKeyValue KeyValue
Else
' Application-defined or object-defined error
Err.Raise 32811
End If
#Else
pDictionary.Remove key
#End If
End Sub
''
' Remove all items
' --------------------------------------------- '
Public Sub RemoveAll()
Attribute RemoveAll.VB_Description = "Remove all information from the dictionary."
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
Set pKeyValues = New Collection
Erase pKeys
Erase pItems
#Else
pDictionary.RemoveAll
#End If
End Sub
' ============================================= '
' Private Functions
' ============================================= '
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
Private Function GetKeyValue(key As Variant) As Variant
On Error Resume Next
GetKeyValue = pKeyValues(GetFormattedKey(key))
Err.Clear
End Function
Private Sub AddKeyValue(key As Variant, value As Variant, Optional Index As Long = -1)
If Me.Count = 0 Then
ReDim pKeys(0 To 0)
ReDim pItems(0 To 0)
Else
ReDim Preserve pKeys(0 To UBound(pKeys) + 1)
ReDim Preserve pItems(0 To UBound(pItems) + 1)
End If
Dim FormattedKey As String
FormattedKey = GetFormattedKey(key)
If Index >= 0 And Index < pKeyValues.Count Then
' Shift keys/items after + including index into empty last slot
Dim i As Long
For i = UBound(pKeys) To Index + 1 Step -1
pKeys(i) = pKeys(i - 1)
If VBA.IsObject(pItems(i - 1)) Then
Set pItems(i) = pItems(i - 1)
Else
pItems(i) = pItems(i - 1)
End If
Next i
' Add key/item at index
pKeys(Index) = key
If VBA.IsObject(value) Then
Set pItems(Index) = value
Else
pItems(Index) = value
End If
' Add key-value at proper index
pKeyValues.Add Array(FormattedKey, key, value), FormattedKey, Before:=Index + 1
Else
' Add key-value as last item
If VBA.IsObject(key) Then
Set pKeys(UBound(pKeys)) = key
Else
pKeys(UBound(pKeys)) = key
End If
If VBA.IsObject(value) Then
Set pItems(UBound(pItems)) = value
Else
pItems(UBound(pItems)) = value
End If
pKeyValues.Add Array(FormattedKey, key, value), FormattedKey
End If
End Sub
Private Sub ReplaceKeyValue(KeyValue As Variant, key As Variant, value As Variant)
Dim Index As Long
Dim i As Integer
Index = GetKeyIndex(KeyValue(1))
' Remove existing Value
RemoveKeyValue KeyValue, Index
' Add new Key Value back
AddKeyValue key, value, Index
End Sub
Private Sub RemoveKeyValue(KeyValue As Variant, Optional ByVal Index As Long = -1)
Dim i As Long
If Index = -1 Then
Index = GetKeyIndex(KeyValue(1))
End If
If Index >= 0 And Index <= UBound(pKeys) Then
' Shift keys/items after index down
For i = Index To UBound(pKeys) - 1
pKeys(i) = pKeys(i + 1)
If VBA.IsObject(pItems(i + 1)) Then
Set pItems(i) = pItems(i + 1)
Else
pItems(i) = pItems(i + 1)
End If
Next i
' Resize keys/items to remove empty slot
If UBound(pKeys) = 0 Then
Erase pKeys
Erase pItems
Else
ReDim Preserve pKeys(0 To UBound(pKeys) - 1)
ReDim Preserve pItems(0 To UBound(pItems) - 1)
End If
End If
pKeyValues.Remove KeyValue(0)
RemoveObjectKey KeyValue(1)
End Sub
Private Function GetFormattedKey(key As Variant) As String
If VBA.IsObject(key) Then
GetFormattedKey = GetObjectKey(key)
ElseIf VarType(key) = VBA.vbBoolean Then
GetFormattedKey = IIf(key, "-1__-1", "0__0")
ElseIf VarType(key) = VBA.vbString Then
GetFormattedKey = key
If Me.CompareMode = CompareMethod.BinaryCompare Then
' Collection does not have method of setting key comparison
' So case-sensitive keys aren't supported by default
' -> Approach: Append lowercase characters to original key
' AbC -> AbC___b_, abc -> abc__abc, ABC -> ABC_____
Dim Lowercase As String
Lowercase = ""
Dim i As Integer
Dim Char As String
Dim Ascii As Integer
For i = 1 To VBA.Len(GetFormattedKey)
Char = VBA.Mid$(GetFormattedKey, i, 1)
Ascii = VBA.Asc(Char)
If Ascii >= 97 And Ascii <= 122 Then
Lowercase = Lowercase & Char
Else
Lowercase = Lowercase & "_"
End If
Next i
If Lowercase <> "" Then
GetFormattedKey = GetFormattedKey & "__" & Lowercase
End If
End If
Else
' For numbers, add duplicate to distinguish from strings
' -> 123 -> "123__123"
' "123" -> "123"
GetFormattedKey = VBA.CStr(key) & "__" & CStr(key)
End If
End Function
Private Function GetObjectKey(ObjKey As Variant) As String
Dim i As Integer
For i = 1 To pObjectKeys.Count
If pObjectKeys.Item(i) Is ObjKey Then
GetObjectKey = "__object__" & i
Exit Function
End If
Next i
pObjectKeys.Add ObjKey
GetObjectKey = "__object__" & pObjectKeys.Count
End Function
Private Sub RemoveObjectKey(ObjKey As Variant)
Dim i As Integer
For i = 1 To pObjectKeys.Count
If pObjectKeys.Item(i) Is ObjKey Then
pObjectKeys.Remove i
Exit Sub
End If
Next i
End Sub
Private Function GetKeyIndex(key As Variant) As Long
Dim i As Long
For i = 0 To UBound(pKeys)
If VBA.IsObject(pKeys(i)) And VBA.IsObject(key) Then
If pKeys(i) Is key Then
GetKeyIndex = i
Exit For
End If
ElseIf VBA.IsObject(pKeys(i)) Or VBA.IsObject(key) Then
' Both need to be objects to check equality, skip
ElseIf pKeys(i) = key Then
GetKeyIndex = i
Exit For
End If
Next i
End Function
#End If
Private Sub Class_Initialize()
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
Set pKeyValues = New Collection
Erase pKeys
Erase pItems
Set pObjectKeys = New Collection
#Else
Set pDictionary = CreateObject("Scripting.Dictionary")
#End If
End Sub
Private Sub Class_Terminate()
#If Mac Or Not UseScriptingDictionaryIfAvailable Then
Set pKeyValues = Nothing
Set pObjectKeys = Nothing
#Else
Set pDictionary = Nothing
#End If
End Sub
Attribute VB_Name = "frmPodbor"
Attribute VB_Base = "0{41EBBF71-48EE-438D-A52E-BB6BCAF5B314}{EDAF2A77-9A7D-4733-AD3A-CD8CB4A9F0A1}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = False
Option Explicit
'Функции API, применяемые для поиска окна и изменения его стиля
#If VBA7 Then
Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function DrawMenuBar Lib "user32" (ByVal hWnd As LongPtr) As Long
#Else
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function DrawMenuBar Lib "user32.dll" (ByVal hWnd As Long) As Long
#End If
'константы для функций API
Private Const GWL_STYLE As Long = -16& 'для установки нового вида окна
Private Const GWL_EXSTYLE = -20& 'для расширенного стиля окна
Private Const WS_CAPTION As Long = &HC00000 'определяет заголовок
Private Const WS_BORDER As Long = &H800000 'определяет рамку формы
Public ActiveRow As Long
Private GoodAmoFlag As Boolean
Private MonoBrand As String
Private MonoSite As String
Private MonoUrl As String
Private OnOnline As Boolean
Private pcsName As String
Private retPack As Integer
Private MyX As Single, MyY As Single
Private Sub UserForm_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
MyX = X
MyY = Y
End Sub
Private Sub lblCaption_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
MyX = X
MyY = Y
End Sub
Private Sub imgPhoto__MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
MyX = X
MyY = Y
End Sub
Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim LastX As Single, LastY As Single
If Button = 1 And MyX > 0 Then
Me.Move Me.Left + X - MyX, Me.Top + Y - MyY
End If
End Sub
Private Sub lblCaption_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim LastX As Single, LastY As Single
If Button = 1 And MyX > 0 Then
Me.Move Me.Left + X - MyX, Me.Top + Y - MyY
End If
End Sub
Private Sub imgPhoto__MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim LastX As Single, LastY As Single
If Button = 1 And MyX > 0 Then
Me.Move Me.Left + X - MyX, Me.Top + Y - MyY
End If
End Sub
Private Sub UserForm_Initialize()
Dim ihWnd, hStyle
'ищем окно формы среди всех открытых окон
If Val(Application.Version) < 9 Then
ihWnd = FindWindow("ThunderXFrame", Me.Caption) 'для Excel 97
Else
ihWnd = FindWindow("ThunderDFrame", Me.Caption) 'для Excel 2000 и выше
End If
'получаем информацию о найденном окне(стили и т.д.)
hStyle = GetWindowLong(ihWnd, GWL_STYLE)
'назначаем переменной новый стиль для окна формы
hStyle = hStyle And Not WS_CAPTION And Not WS_BORDER
'изменяем вид окна: убираем меню(заголовок) и рамку
SetWindowLong ihWnd, GWL_STYLE, hStyle
SetWindowLong ihWnd, GWL_EXSTYLE, 0
'перерисовываем форму, точнее строку меню(заголовка)
DrawMenuBar ihWnd
'меняем размер формы, т.к. сделали смещение элементов формы вверх на высоту заголовка
Me.Height = Me.Height + GWL_EXSTYLE
End Sub
Sub ShowForm(MyRow As Long)
ActiveRow = MyRow
Me.lblCaption = Range(wsPrice & colProdName & ActiveRow) & " - " & Range(wsPrice & colType & ActiveRow)
LoadImg
LoadPack
LoadOrder
Me.txtAmount = Val(Range(wsPrice & colOrder & MyRow))
Me.lstVariants.visible = False
Dim S, SS() As String
SS = Split(ProdactSiteBrands, ",")
MonoBrand = ""
For Each S In SS
If InStr(1, Range(wsPrice & colProdName & ActiveRow).value, S, vbTextCompare) > 0 Then
MonoBrand = S
If GetParam("OnLine") Then
OnOnline = True
If S = "garin" Then MonoBrand = MonoBrand & "-tm"
MonoSite = Replace(ProdactSiteName, "#BRAND#", MonoBrand)
MonoUrl = Replace(Replace(ProdactSiteUrl, "#BRAND#", MonoBrand), "#TID#", Range(wsPrice & colCode & ActiveRow))
End If
Exit For
End If
Next
ShowVariants False
With txtAmount
.SelStart = 0
.SelLength = Len(txtAmount.Text)
End With
Me.Show
End Sub
Sub LoadPack()
Dim packLine As String, Pack, Packs, Stock As Long, tType As String, tName As String, S As String
Stock = Range(wsPrice & colStock & ActiveRow)
retPack = Range(wsPrice & colRetPack & ActiveRow)
retPackMode = Len(Range(rCustomerPPA)) > 5
tType = Range(wsPrice & colProdType & ActiveRow)
tName = Range(wsPrice & colProdName & ActiveRow)
If retPackMode And retPack > 1 Then
'Для ритэйл упаковки
If InStr(tName, "BL") > 0 Then
S = "Блистер"
pcsName = "BL"
ElseIf InStr(tName, "SR") > 0 Then
S = "Шринк"
pcsName = "SR"
Else
S = "Упаковка"
pcsName = "BOX"
End If
S = S & " (" & pcsName & ") содержит "
S = S & retPack & " "
If InStr(tType, "Элемент") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Элемента"
Else
S = S & "Элементов"
End If
ElseIf InStr(tType, "Аккумулятор") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Аккумулятора"
Else
S = S & "Аккумуляторов"
End If
ElseIf InStr(tType, "Батарея") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Батареи"
Else
S = S & "Батарей"
End If
ElseIf InStr(tType, "Лампа") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Лампы"
Else
S = S & "Ламп"
End If
ElseIf InStr(tType, "Разъём") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Разъёма"
Else
S = S & "Разъёмов"
End If
ElseIf InStr(tType, "диск") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Диска"
Else
S = S & "Дисков"
End If
ElseIf InStr(tType, "Штекер") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Штекера"
Else
S = S & "Штекеров"
End If
ElseIf InStr(tType, "Заглушка") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Заглушки"
Else
S = S & "Заглушек"
End If
ElseIf InStr(tType, "клемм") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Клеммы"
Else
S = S & "Клемм"
End If
ElseIf InStr(tType, "Коннектор") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Коннектора"
Else
S = S & "Коннекторов"
End If
ElseIf InStr(tType, "Перчатки") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Перчатки"
Else
S = S & "Перчаток"
End If
ElseIf InStr(tType, "Гриппер") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Гриппера"
Else
S = S & "Грипперов"
End If
ElseIf InStr(tType, "Освежитель") > 0 Then
If retPack > 1 And retPack < 5 Then
S = S & "Освежителя"
Else
S = S & "Освежителей"
End If
Else
If retPack > 1 And retPack < 5 Then
S = S & "Штуки"
Else
S = S & "Штук"
End If
End If
lblStock_.Caption = "!" & S & vbNewLine
pcsName = " " & pcsName
Else
pcsName = " Шт."
lblStock_.Caption = ""
End If
lblStock_.Caption = lblStock_.Caption & Replace("Для заказа доступно " & Format(Stock, "# ##0") & pcsName, " ", " ")
'Список упаковок
packLine = Range(wsPrice & colPackLine & ActiveRow)
Packs = Split(packLine, "/")
lstPackList.AddItem Trim(pcsName)
lstPackList.Column(1, 0) = 1
For Each Pack In Packs
If Pack > 1 Then lstPackList.AddItem "Упак. по " & Pack & pcsName
lstPackList.Column(1, lstPackList.ListCount - 1) = Pack
If Pack > 1 Then If Stock \ Pack > 0 Then lblStock_.Caption = lblStock_.Caption & vbNewLine & Replace("или " & Format(Stock \ Pack, "# ##0") & " упак. по " & Pack & pcsName, " ", " ")
Next
lstPackList.ListIndex = 0
If Stock > 0 Then
lblCaption.BackColor = &HCC9900
lblCaptionPlus.BackColor = &HCC9900
Else
lblCaption.Caption = "ТОВАРА ВРЕМЕННО НЕТ НА СКЛАДЕ!!! " & lblCaption.Caption
lblCaption.BackColor = &HFF&
lblCaptionPlus.BackColor = &HFF&
End If
End Sub
Sub LoadOrder()
Dim LastOrderQty As Long, LastOrderDate As Date
LastOrderQty = Range(wsPrice & colLastOrderQty & ActiveRow)
If LastOrderQty > 0 Then
LastOrderDate = CDate(Range(wsPrice & colLastOrderDate & ActiveRow))
If retPackMode And retPack > 1 Then
lblLastOrder_.Caption = "Дата: " & LastOrderDate & " (" & Int(Now()) - LastOrderDate & " дней назад)" & _
vbNewLine & "Количество: " & LastOrderQty / retPack & pcsName & _
vbNewLine & "Цена: " & Range(wsPrice & colLastOrderPrice & ActiveRow) * retPack & " руб."
Else
lblLastOrder_.Caption = "Дата: " & LastOrderDate & " (" & Int(Now()) - LastOrderDate & " дней назад)" & _
vbNewLine & "Количество: " & LastOrderQty & pcsName & _
vbNewLine & "Цена: " & Range(wsPrice & colLastOrderPrice & ActiveRow) & " руб."
End If
ElseIf Range(wsPrice & colStatus & ActiveRow).value = 2 Then
lblLastOrder_.Caption = "ТОВАР НОВИНКА!" & vbNewLine & "Эта позиция появилась в нашем ассортименте после " & Range(rLastOrderDate)
Else
lblLastOrder_.Caption = "Вы заказываете этот товар впервые."
End If
btnCopyQtyFromLastOrder.Enabled = (LastOrderQty > 0)
End Sub
Sub LoadImg()
Const DummyImgLen As Long = 9595 'Примечание: Изображение Пустышка имеет длину 9595 и игнорируется при загрузке
Dim LocalFile As String
Dim ImgFileName As String
On Error GoTo Err
Me.lblImgError_.visible = False
ImgFileName = Range(wsPrice & colCode & ActiveRow) & ".jpg"
'Полный путь
LocalFile = GetParam("ImgPath") & "\" & ImgFileName
'Если пустышка, то убиваем
If Len(Dir(LocalFile)) > 2 Then If FileLen(LocalFile) = DummyImgLen Or FileLen(LocalFile) = 0 Then Kill LocalFile
'Если локального ещё нет, то скачиваем
If Len(Dir(LocalFile)) < 3 Then
If Len(MonoBrand) > 0 Then
If OnOnline Then
Application.StatusBar = "Загрузка изображения товара ... (Вы можете загрузить сразу все изображения в диалоге Установок)"
DownloadFileNew "JPG", Range(rImgBaseUrl) & Range(wsPrice & colCode & ActiveRow) & ".jpg", LocalFile
Application.StatusBar = False
End If
Else
If GetParam("OnLine") Then
Application.StatusBar = "Загрузка изображения товара ... (Вы можете загрузить сразу все изображения в диалоге Установок)"
DownloadFileNew "JPG", Range(rImgBaseUrl) & Range(wsPrice & colCode & ActiveRow) & ".jpg", LocalFile
Application.StatusBar = False
End If
End If
End If
imgPhoto_.Picture = loadPicture(LocalFile)
SetResize
Exit Sub
Err:
Me.lblImgError_.visible = True
SetResize
End Sub
'=============================================================
Sub ShowVariants(SetShow As Boolean)
lstVariants.visible = SetShow
lblVariants.visible = SetShow
If Len(MonoBrand) > 0 And OnOnline Then
btnProdactInfo.visible = Not SetShow
btnProdactInfo.Caption = "Нужно больше информации? Откройте этот товар на сайте " & MonoSite
Else
btnProdactInfo.visible = False
End If
End Sub
Sub ReCalc()
Dim Amo As Long, AmoCalc As Long
Amo = Val(Me.txtAmount)
AmoCalc = Amo
If Me.lstPackList.ListIndex > 0 Then
'Если по упаковкам, то количество не парит
GoodAmoFlag = True
AmoCalc = Me.lstPackList.Column(1, Me.lstPackList.ListIndex) * Amo
ShowVariants False
Else
'Надо показать варианты
Dim packLine As String, Pack, Packs
Dim IamFirst As Boolean
IamFirst = True
packLine = Range(wsPrice & colPackLine & ActiveRow)
Packs = Split(packLine, "/")
GoodAmoFlag = (Amo / Packs(0) = Amo \ Packs(0))
If Not GoodAmoFlag Then
lstVariants.Clear
ShowVariants True
For Each Pack In Packs
If Amo < Pack Then
'Если меньше минимальной упаковки
If ((Pack - Amo) < Amo / 2 Or IamFirst) And IsNotInVariants(Pack) Then
lstVariants.AddItem "+" & Pack - Amo & " --> " & Pack & pcsName
lstVariants.Column(1, lstVariants.ListCount - 1) = Pack
End If
Else
'Если кратность, даём больше и меньше
If (Amo \ Pack + 1) * Pack - Amo < Amo / 2 And IsNotInVariants((Amo \ Pack + 1) * Pack) Then
lstVariants.AddItem "+" & (Amo \ Pack + 1) * Pack - Amo & " --> " & (Amo \ Pack + 1) * Pack & pcsName
lstVariants.Column(1, lstVariants.ListCount - 1) = (Amo \ Pack + 1) * Pack
End If
If Amo - (Amo \ Pack) * Pack < Amo / 2 And IsNotInVariants((Amo \ Pack) * Pack) Then
lstVariants.AddItem (Amo \ Pack) * Pack - Amo & " --> " & (Amo \ Pack) * Pack & pcsName
lstVariants.Column(1, lstVariants.ListCount - 1) = (Amo \ Pack) * Pack
End If
End If
IamFirst = False
Next
Else
ShowVariants False
End If
End If
'Если неправильное количество, то краснеем
Me.lblBorderUp.BackColor = IIf(GoodAmoFlag, &HC000&, &H40C0&)
Me.lblBorderDown.BackColor = Me.lblBorderUp.BackColor
Me.lblInfo.ForeColor = Me.lblBorderUp.BackColor
Me.lblInfo.Caption = IIf(GoodAmoFlag, AmoCalc & " x " & Range(wsPrice & colPrice & ActiveRow) & _
" = " & Format(AmoCalc * Range(wsPrice & colPrice & ActiveRow), "# ##0.00") & " руб.", "Пожалуйста, уточните количество")
Me.lblAmoCalc = AmoCalc
End Sub
Function IsNotInVariants(MyVal) As Boolean
Dim i, n As Long
IsNotInVariants = True
For n = 0 To Me.lstVariants.ListCount - 1
If Val(Me.lstVariants.Column(1, n)) = MyVal Then
IsNotInVariants = False
Exit Function
End If
Next
End Function
'=============================================================
Sub LoadAmoVars(Amo As Long)
Dim packLine As String, Pack, Packs, Stock As Long
Dim AmoP25 As Long, AmoM13 As Long, IamFirst As Boolean
IamFirst = True
Stock = Range(wsPrice & colStock & ActiveRow)
packLine = Range(wsPrice & colPackLine & ActiveRow)
Packs = Split(packLine, "/")
If Amo / Packs(0) = Amo \ Packs(0) Then
lstVariants.visible = False
lblVariants.visible = False
GoodAmoFlag = True
Else
lstVariants.Clear
lstVariants.visible = True
lblVariants.visible = True
GoodAmoFlag = False
AmoP25 = Amo * 1.25
AmoM13 = Amo * 0.87
For Each Pack In Packs
If Amo < Pack And AmoP25 > Pack Then
lstVariants.AddItem "+" & Pack - Amo & " --> " & Pack & pcsName
ElseIf Amo < Pack And IamFirst Then
lstVariants.AddItem "+" & Pack - Amo & " --> " & Pack & pcsName
End If
If Amo > Pack And AmoM13 < Pack Then lstVariants.AddItem Pack - Amo & " --> " & Pack & pcsName
IamFirst = False
Next
End If
End Sub
Sub SaveAmount()
Dim MyDialog As Integer
Dim qString As String
Dim MyStock As Long
If GoodAmoFlag Then
If Val(Me.lblAmoCalc) > 0 Then
MyStock = Range(wsPrice & colStock & ActiveRow).value
If MyStock < Val(Me.lblAmoCalc) Then
If MyStock = 0 Then
qString = "Исключить этот товар из заказа?"
Else
qString = "Сократить заказываемое количество до " & MyStock & " шт.?"
End If
MyDialog = MsgBox("Товар: " & Range(wsPrice & colProdName & ActiveRow).value & _
vbNewLine & "Тип: " & Range(wsPrice & colType & ActiveRow).value & _
vbNewLine & _
vbNewLine & "Заказываемое количество: " & Val(Me.lblAmoCalc) & _
vbNewLine & "Превышает имеющееся: " & MyStock & _
vbNewLine & _
vbNewLine & qString, vbYesNoCancel + vbQuestion, "Недостаточное количество на складе!")
If MyDialog = vbCancel Then
Exit Sub
ElseIf MyDialog = vbYes Then
Me.lblAmoCalc = MyStock
SaveAmount
Exit Sub
End If
Range(wsPrice & colOrder & ActiveRow) = Val(Me.lblAmoCalc)
Else
Range(wsPrice & colOrder & ActiveRow) = Val(Me.lblAmoCalc)
End If
Else
Range(wsPrice & colOrder & ActiveRow) = ""
End If
Unload Me
Else
MsgBox "Введённое количество не соответсвует минимальным упаковкам. Пожалуйста измените количество и повторите ввод." & vbNewLine & "Вы можете использовать кнопки [+] и [-] или предложенный список вариантов под полем ввода.", vbInformation
End If
End Sub
'============================================================
Private Sub btnCancel_Click()
Unload Me
End Sub
Private Sub btnCancelKeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 39 Then
…
|
|||
vbaProject_00.bin |
vba-project | OOXML VBA project: xl/vbaProject.bin | 452608 bytes |
SHA-256: e4a5b60eb0ebecd5dfd7bc46f106103bebdd93fa465f362e93802805161fe19d |
|||
Open this report in the interactive analyzer, or submit your own file for analysis.