mercoledì 23 marzo 2016

Simulare Check Box in una cella : Simulate CheckBox in cell

ITA:
La procedura CheckSign_Set:
- Trasforma la prima cella di rRange in una check box
- Applica il segno di spunta se bValue è TRUE
- Il parametro Style determina lo stile della chekbox
La funzione CheckSign_Get restituisce True se individua un segno di spunta valido
La funzione CheckSign_Switch inverte lo stato della spunta, restituisce true se individua una spunta nella prima cella di rRange
La funzione getSign determina il caratte da unsare in base a valore e stile.

ENG:
The procedure CheckSign_Set:
- Transform the first cell of rrange in a check box
- Draws the check mark if bValue is TRUE
- The Style parameter determines the style of chekbox
The CheckSign_Get function returns True if detects a valid check mark
The CheckSign_Switch function reverses the state of the check, it returns true if finds a tick in the first cell of rrange
The function determines the getSign char to use based on value and style

'
'
' Determina il carattere da usare per il segno di 
' Determines the font to use for the sign
Private Function GetSign(bValue As Boolean, Optional style As String = "X") As String
  '       Stili validi sono:   - Valid Styles are:
  ' X =ý  'Quadretto Crocetta  - Square box with cross sign
  ' V =þ  'Quadretto Spunta    - Square box with check sign
  ' x =û  'Solo Crocetta       - cross sign without box
  ' v =ü  'Solo Spunta         - check sign without box
  '   =¨  'Quadratto vuoto     - Empty box
  Dim i As Integer
  GetSign = ""
  i = InStr("XVxv", style): If i = 0 Then i = 1
  If bValue Then
    GetSign = Mid$("ýþûü", i, 1)
  Else
    GetSign = Mid$("¨¨  ", i, 1)
  End If
End Function
'
' Imposta il segno di spunta in una cella
' Sets check mark in a cell
'
Sub CheckSign_Set(rRange As Range, bValue As Boolean, Optional Style As String = "X")
Dim c0 As String * 1, c1 As String * 1
  
  With rRange.Cells(1, 1)
    .Value = GetSign(bvalu, style)
    .Font.Name = "Wingdings"
  End With
End Sub
'
' Legge il segno di spunta dalla prima cella di rRange 
' Read Check Mark in the first cell of rRange
'
Function CheckSign_Get(rRange As Range) As Boolean
  With rRange.Cells(1, 1)              ' Legge solo la prima cella;  Read only first cell;
    If .Font.Name = "Wingdings" Then   ' Solo se il font è Wingding; Only for Wingding font; 
      CheckSign_Get = (InStr("ýþûü", .Value) > 0)
    End If
  End With
End Function
'
' Inverte il segno di spunta
' Reverses the checkmark
'
Function CheckSign_Switch(rRange As Range, Optional style As String = "X") As Boolean
  With rRange.Cells(1, 1)
    If .Font.Name = "Wingdings" Then
    ' If .value is empty add a space
      Select Case InStr("ýþûü¨ ", .Value & IIf(Len(.Value) = 0, " ", ""))
      Case 1, 2               ' Boxed
        .Value = "¨"
      Case 3, 4               ' Unboxed
        .Value = " "
      Case 5, 6               ' Not checke, use style
        .Value = GetSign(True, style)
      End Select
      CheckSign_Switch = True ' Checkbox changed
    End If
  End With
End Sub

' ITA:
' Aggiungere questo codice nella dichiarazione del foglio di lavoro, 
' se si desidera modificare lo stato della casella con un doppio clic.
'
' END:
' Add this code in worksheet declaration, if you want to change the status 
' of check box with a double click.
'
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  If Target.Font.Name = "Wingdings" Then
    Cancel = CheckSign_Switch(Target, "X")
  End If
End Sub


lunedì 21 marzo 2016

Espande il contenuto di una variabile ambiente

Questa funzione torna utile per leggere il contenuto di variabili di ambiente come %TEMP% o %PATH% Usefull for read and expand Environmen Variabiles like %TEMP% or %PATH%
'
' Legge una variabile ambiente e ne espande il contenuto
' Reda Environment Variable and expand it
'
Function ExpandEnvironment(sVariableName As String) As String
Dim WshShell
  
  Set WshShell = CreateObject("WScript.Shell")
  ExpandEnvironment = WshShell.ExpandEnvironmentStrings(sVariableName)
  Set WshShell = Nothing
End Function

SendKeys con Windows7

'
' Sostisuisce la funzione Sendkeys che non funziona con i SO successivi a XP
' Replaces Sendkeys internal function has problems with operating systems more than XP
'
Sub SendKeys7(sKeyString As String, Optional bWait As Boolean = False)
Dim WshShell As Object
  
  Set WshShell = WScript.CreateObject("WScript.Shell")
  WshShell.SendKeys sKeyString, bWait
  Set WshShell = Nothing
End Sub

sabato 19 marzo 2016

Excel VBA Context menu

ITA: Per aggiungere un menu contestuale, richiamare PreparamenuContestuale nell'evento evento Workbook_Open.
Per vializzare il menu usare una chiamata nell'evento Worksheet_BeforeRightClick (vedi esempio).
Nell'esempio viene aggiunta solo una voce di menu, ma posiamo aggiungere altre voci di menu o altri menu.
Puoi scegliere il codice FaceID da questa pagina o altre simili in rete.
ENG: You can add contextual menu by adding a call to PreparaMenuContestuale into Workbook_Open event.
You can display context menu by calling it into Worksheet_BeforeRightClick event (see below example).
In this example only one menu item are added, but you can add more items and more menus.
You can view FaceID code in this page or others similar in the net. FaceID
'
' Add Command Bar Items
'
Sub PreparaMenuContestuale(Optional dummy As Boolean = False)
Dim ContextMenu As CommandBarPopup
Dim sName   As String
Dim sAction As String
Dim sTag    As String
Dim i       As Long

  sName = "contextMenuName"
  sAction = "'" & ThisWorkbook.Name & "'!PLG_"  ' Base Name of the code called by menu PLG_ are sample
  sTag = "Tag_PLG"                              ' Tag for alla items in this menu
  DeleteFromCommandBar sName                    ' Removing if already present
  
  With Application.CommandBars.Add( _
      Name:=sName, Position:=msoBarPopup, _
      MenuBar:=False, Temporary:=True)          ' Add new command bar menu
    With .Controls.Add(Type:=msoControlButton)  ' Add first munu item
      .Caption = "Modifica Articolo"            ' What you see in menu
      .TAG = sTag                               ' Used for searching
      .OnAction = sAction & "ModificaArticolo"  ' Name of procedure called
      .FaceId = 2059                            ' ID of image used in menu (optional)
      .DescriptionText = _
         "Modifica le proprietà dell'articolo " ' Hint for this menu item
      .TooltipText = .DescriptionText           ' What you see in tootip text Ballon
    End With
  End With
End Sub
'
' Remove command Bar specified by name
'
Sub DeleteFromCommandBar(sCommandBarName As String)
On Error Resume Next
  
  With Application.CommandBars(sCommandBarName)
    If Error.Number = 0 Then
      .Delete
    End If
  End With
  Error.Clear
On Error GoTo 0
End Sub
'
' Remove alla the item with specidied tag from commandBarMenu specified by name
' if tag is empty rempve all items
'
Sub DeleteFromCommandBarTAG(sCommandBarName As String, Optional sTag As String = "")
Dim ContextMenu As CommandBar
Dim ctrl As CommandBarControl

On Error Resume Next
  ' Define pointer to menu
  Set ContextMenu = Application.CommandBars(sCommandBarName)

  ' Loop for all menu items
  For Each ctrl In ContextMenu.Controls
    If ctrl.Tag = sTag Or sTag = "" Then
    ' Delete when TAG is equal os sTag is empty
      ctrl.Delete
    End If
  Next ctrl
On Error GoTo 0
End Sub

'
' Place this code into worksheet declaration
'
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
  If Target.Row = 3 Then
    If Target.Column < 5 then 
      Cancel = True                                        'Prevent executing of normal Double Click event
      Application.CommandBars("contextMenuName").ShowPopup 'Show Menu
    End If
  End If
End Sub

venerdì 18 marzo 2016

Excel VBA - Pulizia Range (Clear range)

ITA: Semplifica la cancellazione di un range. Aggiunge alcuni metodi non disponibili:
- Cancellazione delle costanti (lascia intatte le formule)
- Cancellazione selettiva dei bordi
- Cancellazione selettiva degli attributi del font
- Cancellazione Colore del fotn e sfondo

ENG: Simplifies range cleaning. It adds some methods not availables
- Constants cleaning (leaves formulas)
- Selective deleteion of edges
- Selective deletion of font attributes
- Cancellation of the background color


'
' Pulisce il range specificato
' Mode è una stringa che può contenere uno p più dei seguenti caratteri:
'
' T=Tutto              (corrisonde al metodo Clear)
' C=Contenuto          (corrisonde al metodo ClearContents) 
' c=Commenti           (corrisonde al metodo ClearComments)  
' F=Formati            (corrisonde al metodo ClearFormats)  
' N=Note               (corrisonde al metodo ClearNotes)   
' H=Hyperlink          (corrisonde al metodo ClearHyperlinks)   
' O=Outline            (Struttura)
' V=Valori             (non cancella le formule)
' P=Paper color        (Colore sfondo)
' f=Font Attribute     Cancella gli attributi del font, è possibile specificare quali
'                      indicando una combinazione delle lettere [GCBAPSNDI] racchiuse tra []
'                      Grasetto/Corsivo/Barrato/Apice/Pedice/Sottolineato
'                      Nome font/Dimensioni font (ripristina i predefiniti)
'                      Inchiostro (colore del carattere)
' B=Bordi              Cancella i bordi, è possibile specificare quali
'                      indicando una combinazione delle lettere [LTBRVHDU] racchiuse tra []
'                      Left/Top/Bottom/Right; inside Vertical/Horizontal; diagonal Up/Down
'

' Clean specificed range
' Mode is a string than can containing ono or more of this chars:
'
' T=all                (equivalent to Clear          method)
' C=Contents           (equivalent to ClearContents  method)
' c=Comments           (equivalent to ClearComments  method) 
' F=Formats            (equivalent to ClearFormats   method)
' N=Notes              (equivalent to ClearNotes     method)
' H=Hyperlink          (equivalent to ClearHypelinks method)
' O=Outline            (equivalent to ClearOutline   method)
' V=Values             (clear only constants, leave formulas)
' P=Paper color        (clear background color of cells)
' f=Font Attribute     Clear font attributes. You can specify which indicating a combination 
'                      of the letters [GCBAPSNDI] enclosed in square barckets
'                      G=Bold/C=Italic/B=Strikethrough/A=Superscript/P=Subscript/S=Underlines
'                      N=Font Name/D=Font Size/I=Font Color (restore defaults)
' B=Borders            Clear borders. You can specify which indicating a combination 
'                      of the letters [LTBRVHDU] enclosed in square barckets
'                      L=Left/T=Top/B=Bottom/R=Right
'                      V=inside Vertical/H=inside Inside Horizontal
'                      U=diagonal Up/D=diagonal Down
'
Sub PuliziaRange(rRange As Range, Optional ByVal sMode As String = "C")
Dim sKeys As String

  With rRange
    Do Until sMode = Empty
      Select Case Left$(sMode, 1)
      Case "C"
        .ClearContents
      Case "c"
        .ClearComments
      Case "F"
        .ClearFormats
      Case "H"
        .ClearHyperlinks
      Case "N"
        .ClearNotes
      Case "O"
        .ClearOutline
      Case "V"
      ' Solo i valori, lascia le formule 
      ' Only values, leaves formulas
        Dim c As Range
        For Each c In .Cells
          If c.HasFormula = False Then c.ClearContents
        Next c
      Case "P"
        .Interior.ColorIndex = xlColorIndexNone
      Case "f" ' [GCBAPSNDI]
        sKeys = ""
        If Mid$(sMode, 2, 1) = "[" Then
          sKeys = Parse(Mid$(sMode, 3), "]")                ' clean flags for fonts 
          sMode = "f" & Mid$(TrimBefore(sMode, "]"), 2) ' Remove brackets 
        End If
      
        With .Font
          If KeyExist(sKeys, "G") Then .Bold = False
          If KeyExist(sKeys, "C") Then .Italic = False
          If KeyExist(sKeys, "B") Then .Strikethrough = False
          If KeyExist(sKeys, "A") Then .Superscript = False
          If KeyExist(sKeys, "P") Then .Subscript = False
          If KeyExist(sKeys, "S") Then .Underline = xlUnderlineStyleNone
          If KeyExist(sKeys, "F") Then .Name = Application.StandardFont
          If KeyExist(sKeys, "D") Then .Name = Application.StandardFontSize
          If KeyExist(sKeys, "I") Then .Name = .ColorIndex = xlAutomatic
        End With
        
      Case "B"      ' [LTBRVHDU]
        sKeys = ""
        If Mid$(sMode, 2, 1) = "[" Then
          sKeys = Parse(Mid$(sMode, 3), "]")                ' clean flags for bordes
          sMode = "B" & Mid$(TrimBefore(sMode, "]"), 2) ' Remove brackets 
        End If
        If KeyExist(sKeys, "D") Then .Borders(xlDiagonalDown).LineStyle = xlNone
        If KeyExist(sKeys, "U") Then .Borders(xlDiagonalUp).LineStyle = xlNone
        If KeyExist(sKeys, "L") Then .Borders(xlEdgeLeft).LineStyle = xlNone
        If KeyExist(sKeys, "T") Then .Borders(xlEdgeTop).LineStyle = xlNone
        If KeyExist(sKeys, "B") Then .Borders(xlEdgeBottom).LineStyle = xlNone
        If KeyExist(sKeys, "R") Then .Borders(xlEdgeRight).LineStyle = xlNone
        If KeyExist(sKeys, "V") Then .Borders(xlInsideVertical).LineStyle = xlNone
        If KeyExist(sKeys, "H") Then .Borders(xlInsideHorizontal).LineStyle = xlNone
      Case "T"
        .Clear
      Case Else
        Err.Raise 2001, "PuliziaRange", "Invalid Parameter " & sMode 
      End Select
      sMode = Mid$(sMode, 2)
    Loop
  End With
End Sub

'
' Cerca il carattere sKey nella stringa sKeys
' Se la string sKeys è vuota retituisce bDefault
' il confronto è case sensitive
'
' Find sKey into sKeys. If sKeys is empty return sDefault
' Search are case sensitive
'
Function KeyExist(sKeys As String, sKey As String, _
                  Optional bDefault As Boolean = True) As Boolean
  If Len(sKeys) = 0 Then
    KeyExist = bDefault
  Else
    KeyExist = (InStr(sKeys, sKey) > 0)
  End If
End Function
'
' Scompone una stringa di parametri
' Separati da virgole oppure da un altro carattere a scelta
'
'
' Parse parametre string, separated by commas or other char specified
'
Function Parse(s As String, Optional Sep) As String
Dim c As Integer
  If IsMissing(Sep) Then Sep = ","
  c = InStr(s, Sep)
  Select Case c
  Case 0
    Parse = s
    s = Empty
  Case 1
    Parse = Empty
    s = Mid$(s, 2)
  Case Else
    Parse = Mid$(s, 1, c - 1)
    s = Mid$(s, c + 1)
  End Select
End Function

'
' Cerca nella stringa S la stringa F
' Per default la ricerca è CaseSensitive (specificare vbTextCompare per NoCaseSensitive)
' Se la trova restituisce la parte di stringa S che inizia con F (F compresa)
' Se non la trova restituisce una stringa vuota
'
' Find string S into F, search are CaseSensitive (specify vbTextCompare for NoCaseSensitive)
' If found then return part of S that begins at F position (included)
' If not found then return empty string
'
Function TrimBefore(s As String, f As String, Optional vbCompare As VbCompareMethod = vbBinaryCompare) As String
Dim i As Integer
  
  i = InStr(1, s, f, vbCompare)
  If i > 0 Then
    TrimBefore = Mid$(s, i)
  Else
    TrimBefore = Empty
  End If
End Function


martedì 8 dicembre 2015

Excel VBA - some snippets

Questo post ha il solo scopo di tenere a portata di mano alcune funzioni VBA che uso abbastanza spesso.

This post is only meant to collect some VBA functions that I often use.

'
' Bottom Right corner of range
' Angolo inferiore destro di un range
'
Function LastCellInRange(rRange As Range) As Range
  Set rRange = rRange.Cells(rRange.Rows.cont, Range.Columns.Count)
End Function
'
' Expand Range to non empty row on first column and last column of range
' Espande il range fino alla prima cella non vuota nella prima colonna, e all'ultima colonna del range 
'
Function ExpandRange(rStartRange As Range) As Range

  If rStartRange.Cells(2, 1).empty Then
  ' Range composto da una solo rig
    Set ExpandRange= LastCellInRange(rStartRange)
  Else
    Dim r As Long, c As Integer
    r = rStartRange.Cells(1, 1).End(xlDown).Row
    c = rStartRange.Columns(rStartRange.Columns.Count).Column
    Set ExpandRange= Range(rStartRange.Cells(1, 1), Cells(r, c))
  End If
End Function

martedì 11 novembre 2014

VBA - TimeredShape with FadeIn - FadeOut effect

Oggi inizio la pubblicaizone di alcune procedure VBA che uso con Excel.
Quella di oggi serve per visualizzare una shape, più spesso una casella di testo, per un tempo determinato con un effetto dissolvenza in entrata e in uscita, un po' come quello della nova mail in arrivo di outlook.

Per il funzionamento di questa procedura servono alcune funzioni:

  1. Dichiarare la funzione sleep del kernel, che permetet di definire delle pause in millisecondi senza sprecare cpu.
  2. Procedura FadeInOut, che applica l'efeftto dissolvenza, i parametri sono:
    Oggetto shape al quale applicare l'effetto,
    valore Tree/False per indicare rispettivamente FadeIn o FadeOut,
    durata dell'effetto in msec.
  3. Funzione rgbLum che applica una luminosità in % ad un colore, i parametri sono:
    R,G,B (colore di base), L luminosità compresa tra 0 e 100
  4. Procedura splitRGB traduce nei 3 componenti rgb un colore, i parametri sono:
    l_RGBcolor: colore da trasformare,
    r,g,b: valori in output che conterrano le 3 componenti del colore.


I parametri della procedura principale TimeredShape sono:
Oggetto shape da mostrare;
Tempo di visualizzazione in msec (default 5)
Tempo dell'effetto dissolvenza


[english]
Today I begin the publication of some VBA procedure that I currently use.
TimeredShape is useful for displaying a shape with fadein effect, after waiting for a time in milliseconds hide that with fadeout effect.



Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub FadeInOut(s As Shape, _
              Optional bFadeIN As Boolean = True, _
              Optional lDelayMS As Long = 1000)
Dim i As Integer
Dim iBegin As Integer, iEnd As Integer, iStep As Integer
Dim lDelay As Long
Dim l_Trsp As Long                               ' Final Ttransparency / Trasparenza definitiva
Dim l_ForeColor As Long                          ' Border final color / Colore definitivo bordo
Dim bTrasp As Boolean                            ' Trasparenzy are applicable ? / Trasperenza applicabile ?
Const kScala As Integer = 100
  
  lDelay = CLng(lDelayMS / kScala)               ' Calculate step delay /Calcola il ritardo per ogni step
  Dim r As Integer, g As Integer, b As Integer
  
  l_ForeColor = s.Line.ForeColor                 ' Store line color / Determino il colore dell'oggetto
  splitRGB l_ForeColor, r, g, b                  ' Retrieve r,g,b components / Scompongo i valori RGB
  If s.AutoShapeType <> msoShapeMixed Then       ' Aplly only for fillable shape / Applico solo x shape con proprietà Fill
    l_Trsp = s.Fill.Transparency * kScala        ' Store transparency value / Valore Trasparenza dell'oggetto
    bTrasp = True
  Else
    l_Trsp = 0
    bTrasp = False
  End If
    
  If bFadeIN Then                                ' Define Fade paramters / Definisce i parametri per Fade In e Fade Out
    iBegin = kScala
    iEnd = 0
    iStep = -1
  Else
    iBegin = 0
    iEnd = kScala
    iStep = 1
  End If
  lDelay = lDelay * Abs(iStep)                   ' 
    
  s.Line.ForeColor.RGB = rgbLum(r, g, b, iBegin) ' Initialize colour / Inizializzo il colore
  If bTrasp Then
    s.Fill.Transparency = (l_Trsp + (100 - l_Trsp) * iBegin / kScala) / kScala
  End If
  s.Visible = True                               ' Show shape / Mostra l'oggetto
  For i = iBegin To iEnd Step iStep              ' Fade effect / Effetto dissolvenza
    s.Line.ForeColor.RGB = rgbLum(r, g, b, i)    ' Apply color to border line / Applico il colore alla linea del brodo
    If bTrasp Then                               ' Apply transparency / Applico la trasparenza se esiste fill
      s.Fill.Transparency = (l_Trsp + (100 - l_Trsp) * i / kScala) / kScala
    End If
    DoEvents
    Sleep lDelay
  Next i
  s.Visible = bFadeIN                            ' Show/Hide shape / Mostra/Nasconde oggetto
  If bFadeIN = False Then                        
    s.Line.ForeColor.RGB = l_ForeColor           ' Reapply original colour / Riapplico il colore originale
    If bTrasp Then                               ' 
      s.Fill.Transparency = l_Trsp / kScala      ' Reapply original transparency / Riapplico la trasparenza iniziale
    End If
  End If

    
End Sub
'
' Return color with luminance in % 100=White
' Restituisce il colore corrispondente con una luminosità in %  100%=bianco
'
Function rgbLum(r As Integer, g As Integer, b As Integer, l As Integer) As Long
' Red, Green, Blue, Luminance%
  rgbLum = RGB(r + (255 - r) * l / 100, g + (255 - g) * l / 100, b + (255 - b) * l / 100)
End Function
'
' Retrieve RGC colour component from RGB colour
' Scompone un colore RGB nei 3 componenti
'
Sub splitRGB(lRGBcolor As Long, r As Integer, g As Integer, b As Integer)
Dim s As String
  
  s = Right$("000000" & Hex$(lRGBcolor), 6)
  r = Val("&h" & Mid$(s, 1, 2))
  g = Val("&h" & Mid$(s, 3, 2))
  b = Val("&h" & Mid$(s, 5, 2))
End Sub
' ' Display a shape for a time in msec whith fade effect
' Mostra una shape per i millisecondi indicati + il doppio del tempo di dissolvenza indicato
'
Sub TimeredShape(s As Shape, Optional l_DisplayTimeMS As Long = 5000, Optional l_FadeTime As Long = 2000)
  FadeIn s, True, l_FadeTime
  Sleep l_DisplayTimeMS
  FadeInOut s, False, l_FadeTime
End Sub