Copy Worsheets - Without link

Bonjour,

J'ai besoin d'aide s'il vous plaît. En effet je réalise un utilitaire afin de transformer des anciens fichiers Excel en 32bits en version 64bits. Pourquoi je fais cela ? Parce que j'ai des API en 32bits et que je voudrais les transformer en 64 bits pour continuer d'utiliser le même fichier sans ressaisir l'ensemble des données pour chaque fichier. Pour réaliser cela j'ai mis les mêmes worksheets dans mon utilitaire que le fichier cible, avec juste le code VBA derrière en 64 bits. J'ai fait des recherches sur internet je me suis basé sur ces dernières mais aucune répond à mon problème.

Première question : Je suis pas encore passé en 64 bits (j'attend que mon utilitaire fonctionne avant) et je ne peux donc pas essayer.

Est-ce que je pourrais ouvrir un fichier avec les API 32 bits à partir du 64 bits (par le VBA) si je bloque les recalcule avant ? Ou alors une erreur va être remonté et cela va me remonter une erreur ?

Sinon pour le moment :

Lorsque je copie avec un

ws.cells.copy

destination.cells.pasteSpecial wlPasteAll

ou

destination.Cells.PasteSpecial xlPasteFormulasAndNumberFormats

destination.Cells.PasteSpecial xlPasteColumnWidths

destination.Cells.PasteSpecial xlPasteValidation

destination.Cells.PasteSpecial xlPasteFormats

Les cellules nommées sont liées à l'ancien Excel. Pour résoudre cela :

Je redéfini leur ReferTo en supprimant le "C:\..[ExcelName]" (Assez long)

ou

Je les supprime entièrement pour les reajouter avec le bon ReferTo (plus rapide)

Les contrôles de formulaires (shapes) ne sont pas copiés. Pour résoudre cela :

boucle sur shapes, copy / paste : les copie pas au bon endroit

Redéfinir leurs positions avec .TOP et .LEFT (long)

ou

Les rajouter .Add avec les mêmes caractéristiques (je préfère)

Les variables de certaines formules sont liées avec l'ancien aussi

Remplacer les "C:\.." par rien (super long infaisable)

ou

Remplacer les "=" par "x=" avant de copier uniquement en valeur dans le fichier cible (trop long aussi infaisable)

Question : Est-ce que quelqu'un a une meilleure solution pour réaliser cela ? Car ça me prend 20 mins pour le moment ce qui n'est pas vraiment utilisable au quotidien.

Je suis preneur de toutes suggestions vers laquelle je pourrais me pencher car j'arrive à bout d'idée.

En parallèle je vais me pencher sur l'aspect de modifier directement le code VBA par le VBA. Un aspect que je ne maîtrise pas encore et que je voulais éviter mais si c'est plus rapide.

Je vous remercie d'avance.

Bonjour,

Pour assurer la compatibilité, sauf erreur de ma part, une déclaration des API comme suit suffit généralement

#If Win64 Then 
    Declare PtrSafe Sub ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI)
    Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Declare PtrSafe Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As Long
#Else
    Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
    Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Declare Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As Long
#End If

ceci n'est qu'un exemple

Bonjour,

Issu du fichier Win32API_PtrSafe.txt.

Cdlt.

#if Win64 then
    Declare PtrSafe Function ClientToScreen Lib "user32" (ByVal hwnd As LongPtr, lpPoint As POINTAPI) As Long
    Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Declare PtrSafe Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long
#else
    Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
    Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Declare Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As Long
#End If

Merci de vos réponses, malheureusement cela ne résous pas mon soucis.

Oui je suis d'accord qu'il faut modifier cela entre les deux versions, mais si je suis en 64 bits et que je veux ouvrir un workbook d'il y a 1 an en 32bits avec le code VBA protégé sans connaitre le mot de passe ?

Mon utilitaire permet aux utilisateurs inexpérimentés d'ouvrir mon ancien outil et de l'avoir en version 64 bits sans message d'erreur de partout (ce qui est le cas).

Du coup dans ma première réflexion je copiais l'ensemble des formules, valeurs, formats avec le code derrière en 64bits, les déclarations que vous m'avez donné.

Mais cela est trop long à utiliser avec les liens vers l'ancien, donc je suis parti sur l'idée de modifier le VBA par le VBA. C'est simple de supprimer une fonction et la réécrire, mais je n'arrive pas à récupérer la ligne exacte de cette déclaration d'API avec le :

Wb.VBProject.VBComponents(i).CodeModule.ProcStartLine("ClientToScreen", 0)

Cordialement. ;)

C'est simple de supprimer une fonction et la réécrire, mais je n'arrive pas à récupérer la ligne exacte de cette déclaration d'API avec le :

Wb.VBProject.VBComponents(i).CodeModule.ProcStartLine("ClientToScreen", 0)

D'abord il faut approuver l'accès au modèle d'objets VBA, je pense que tu l'as déjà fait. Je le remets pour la communauté.

approbation acces

Ensuite tu peux balayer tous les modules et toutes les lignes des modules sans te poser de question de la ligne exacte et faire ceci, avec

  • XXXX le texte avant modif
  • ZZZZ le texte après modif
Sub remplacer()
    modifierMacro "XXXX", "ZZZZ"
End Sub

Sub modifierMacro(avant As String, apres As String)
'Nécéssite d'activer la référence "Visual basic For Application Extensibility 5.3"
    For n = 1 To ActiveWorkbook.VBProject.VBComponents.Count
        With ActiveWorkbook.VBProject.VBComponents(n).CodeModule
                For i = 1 To .CountOfLines
                    If .Lines(i, 1) Like "*" & avant & "*" Then
                        modif = .Lines(i, 1)
                        modif = Replace(modif, avant, apres)
                        .ReplaceLine i, modif
                    End If
                Next
        End With
    Next
End Sub

Si tu dois ajouter une ligne, alors c'est différent, il faut réécrire.

Salut !

Ouais parfait je voulais optimiser le temps d'exécution avec le

For Each VBComp In wb.VBProject.VBComponents
        With VBComp.CodeModule
               Debut = .ProcStartLine(MName, 0)
               Lignes = .ProcCountLines(MName, 0)

               .DeleteLines Debut, Lignes
         End With
Next VBComp

Avec MName qui équivaut au fonction que je veux supprimer, mais il ne trouve pas la déclaration de fonction API32bits avec cela.

Donc j'ai du faire comme ce que tu proposes, se balader sur toutes les lignes et supprimer celles qui me plaisait pas.

Avant de réinsérer les API en 64Bits avec des :

.InsertLines "Declare......"

C'est moins propre et plus long que ce que je voulais, mais ça marche, je vais me contenter de cela ;)

Merci de ton aide.

Rechercher des sujets similaires à "copy worsheets without link"