jeudi 5 mars 2020

VBA - Excel - Coller en texte

Parce que ça fait plus de 2 ans qu'on me dit que c'est trop compliqué de gérer le copier valeur depuis une source externe, j'ai pris 2h de mon temps pour me remettre au VBA après de longues années. Bah c'était pas si compliqué...

Il peut-être utile de forcer le coller dans une feuille Excel pour n'en coller que les valeurs sans autres caractéristiques (mise en forme, format de nombre etc.).

Ex.: Sur une feuille servant d'Interface utilisateur avec des contrôles de format (par Macro).
Sans la captation de l’événement "coller" Excel va également prendre en compte les formats ce qui peut être un inconvénient si vous avez spécifié le format et le contrôle associé de votre cellule (problème principalement sur les chiffres et dates).

Ici nous gérons le cas particulier ou la source de données n'est pas Excel, mais une source Externe telle qu'Oracle (On récupère le contenu du presse Papier).

Vous devez activer la librairie suivante (Il est possible de l'activer par Macro également)
'Tools -> References -> Microsoft Forms 2.0 Object Library"

Dans l'éditeur de Macro (alt+F11), dans la feuille *ThisWorkbook* vous devez copier le code suivant :
'-- Prise en compte de la macro à l'ouverture du classeur
'-- L'action se réalise avec Ctrl+v et Ctrl+V (minuscule, majuscule)

Private Sub Workbook_Open()
    Application.CutCopyMode = False ' Rend le presse-papier disponible et vide

    Application.OnKey "^V", "PasteProc"
    Application.OnKey "^v", "PasteProc"
End Sub

'--Créer un module
Option Explicit

Private module
Public Clipboard As New MSForms.DataObject

'--Coller les procédures qui font le job

'--Il y a un respect du standard des tableaux prenant le caractère tabulation comme séparateur de colonne
'--Il ne reste donc plus qu'à tester si j'ai une source Excel ou Presse Papier
Public Sub PasteProc()
    Select Case Application.CutCopyMode
        Case Is = False
            Call PasteExtern
        Case Is = xlCopy
            Call PasteExcel
        Case Is = xlCut
            Call PasteExcel
    End Select
End Sub

Private Sub writeExcelFromClipboard()
'Tools -> References -> Microsoft Forms 2.0 Object Library
'of you will get a "Compile error: user-defined type not defined"
  Dim Clipboard As New MSForms.DataObject
  Dim S As String
  Dim i, j As Double

  Clipboard.GetFromClipboard
    S = Clipboard.GetText

    Dim start_r, start_c
    Dim tab_line() As String
    Dim tab_tab() As String
    ReDim tab_line(UBound(Split(S, vbCrLf)))

    'start_r = ActiveCell.Row '.Address
    'start_c = ActiveCell.Column
   
    tab_line = Split(S, vbCrLf)
    For i = 0 To UBound(tab_line)
      ReDim tab_tab(UBound(Split(tab_line(i), vbTab)))
      tab_tab = Split(tab_line(i), vbTab)
      For j = 0 To UBound(tab_tab)
        ActiveCell.NumberFormat = "@"
        'ActiveCell.Offset(start_r + i, start_c + j).Value = tab_tab(j)
        ActiveCell.Offset(i, j).Value = tab_tab(j)
      Next j
    Next i

  'readClipboard = S
End Sub

Private Sub PasteExcel()
  'Selection.NumberFormat = "@"
  'ActiveSheet.Paste
  Selection.PasteSpecial Paste:=xlPasteValues
End Sub

Private Sub PasteExtern()
  'ActiveCell.Value2 = readClipBoard 'Clipboard.GetFromClipboard
  Call writeExcelFromClipboard
  Clipboard.Clear
End Sub