Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenOffice & LibreOffice Discussion :

Optimisation temps automation Libre Office


Sujet :

OpenOffice & LibreOffice

  1. #1
    Membre du Club
    Optimisation temps automation Libre Office
    Bonjour,
    J'utilise calc via vb.net sous visual studio. Mon soucis est de réduire le temps d'ouverture, lecture d'un fichier.

    De ce que j'ai relevé:

    2.3 à 2.6 secondes
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Dim ServiceManager As Object = CreateObject("com.sun.star.serviceManager")


    5 ms
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Desktop = ServiceManager.createInstance("com.sun.star.frame.Desktop")


    400 à 450 ms
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    OpenPar(0) = MakePropertyValue("ReadOnly", False)
    OpenPar(1) = MakePropertyValue("Password", "")
    OpenPar(2) = MakePropertyValue("Hidden", True)
    MyDocument = Desktop.loadComponentFromURL(FilePath, "_blank", 0, OpenPar)
    Dim MySheet As Object = MyDocument.getSheets.getByName("DEMILUNEF_3")


    8 à 10 secondes
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
                ' Get first empty cell
                Dim oCurseur As Object
                oCurseur = MySheet.createCursor
                oCurseur.gotoEndOfUsedArea(False)
                Dim Longueur As Integer = oCurseur.RangeAddress.EndRow
     
                Dim a As Long = (Date.Now.Second * 1000) + Date.Now.Millisecond
     
                ' Get first range and fill array with datas (course mm)
                Dim PlageCellules As Object = MySheet.getCellRangeByName("A2:A" & Longueur + 1)
                Dim Plages As Object = MyDocument.createInstance("com.sun.star.sheet.SheetCellRanges")
                Plages.insertByName("", PlageCellules)
                Dim oEnum As Object = Plages.Cells.CreateEnumeration
                Dim index As Integer = 0
                ReDim Signal1(Longueur - 1)
                While oEnum.hasMoreElements
                    Dim Cellule As Object = oEnum.NextElement
                    Signal1(index) = Cellule.String
                    index = index + 1
                End While
     
                ' Get second range and fill array with datas (mechanical stress)
                PlageCellules = MySheet.getCellRangeByName("B2:B" & Longueur + 1)
                Plages = MyDocument.createInstance("com.sun.star.sheet.SheetCellRanges")
                Plages.insertByName("", PlageCellules)
                oEnum = Plages.Cells.CreateEnumeration
                index = 0
                ReDim Signal2(Longueur - 1)
                While oEnum.hasMoreElements
                    Dim Cellule As Object = oEnum.NextElement
                    Signal2(index) = Cellule.String
                    index = index + 1
                End While


    Donc en gros mes deux points à optimiser seraient le service manager et la boucle de récupération des données. Il y a 9300 lignes pour chacune des 2 colonnes donc enormement d'iterations.
    Je ne sais pas si on peut copier par blocs ou utiliser marshal pour une copie memoire... Bref je n'ai pas beaucoup de pistes.

    Merci pour votre aide

  2. #2
    Membre du Club
    Bon, j'essaye de passer par le presse papier, ça devrait aller plus vite par contre j'ai une erreur quand j'execute le dispatch... et pas beaucoup de details dans l'erreur. C'est la fonction "Dispatcher.executeDispatch" qui me dit "Le type ne correspond pas. (Exception de HRESULT : 0x80020005 (DISP_E_TYPEMISMATCH))"

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     
     
                ' Select cellule range
                Dim oCC As Object, Cellule As Object
                Dim Args As New unoidl.com.sun.star.beans.PropertyValue()
                oCC = MyDocument.CurrentController
                Cellule = oCC.ActiveSheet.getCellRangeByName("A6")
                oCC.Select(Cellule)
     
                ' Paste
                Dim Dispatcher As Object
                Dispatcher = CreateUnoService("com.sun.star.frame.DispatchHelper")
                Dispatcher.executeDispatch(oCC.Frame, ".uno:Copy", "", 0, Args)

  3. #3
    Membre du Club
    J'ai fait plusieurs essais, c'est vraiment la syntaxe de args qui ne plait pas... Je ne trouve pas la bonne syntaxe car cela fonctionne bien sur une macro.

    vba
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Dim Args() As new com.sun.star.beans.PropertyValue


    vb.net

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Dim Args() As unoidl.com.sun.star.beans.PropertyValue


    j'ai esssayé ça aussi mais bon...

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Dim Args As New unoidl.com.sun.star.beans.PropertyValue()

  4. #4
    Expert confirmé
    hello,
    j'ai testé la lecture par tableaux au lieu de la lecture cellule par cellule en code VBA qui attaque un classeur calc (les 9300 cellules de la première colonne sont remplies avec une série (1,2,3 etc... )) avec ce code :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    Sub OuvreOOoCalc()Rem
    Rem Charger un document  calc
    Rem
      Dim oSM, ODesk, oClasseur, oFeuille, oCurseur As Object 'Les objets de base de OOo
      Dim OpenPar(2) As Object 'Un tableau VB
      Dim T As Double
      T = Timer
    'Instancie OOo : ces deux lignes sont obligatoires avec VB dans tout code !
     Set oSM = CreateObject("com.sun.star.ServiceManager")
     Set ODesk = oSM.createInstance("com.sun.star.frame.Desktop")
     
     
    'On appelle la fonction setOOoProp définie précédemment pour récupérer la structure
      Set OpenPar(0) = setOOoProp(oSM, "ReadOnly", True)
      Set OpenPar(1) = setOOoProp(oSM, "Password", "secret")
      Set OpenPar(2) = setOOoProp(oSM, "Hidden", False)
     T1 = Timer
    'On appelle la fonction OOo loadComponentFromURL, en lui passant en
    'dernier paramètre le résultat de la fonction setOOoProp
     Set oClasseur = ODesk.loadComponentFromURL("file:///M:/test/test.ods", "_blank", 0, OpenPar)
     T2 = Timer
     Set oFeuille = oClasseur.getSheets.getByName("DEMILUNEF_3")
     Set oCurseur = oFeuille.createCursor
     oCurseur.gotoEndOfUsedArea (False)
     Dim Longueur As Integer
     Longueur = oCurseur.RangeAddress.EndRow
     Dim a As Long
     Dim PlageCellules As Object
     Set PlageCellules = oFeuille.getCellRangeByName("A2:A" & Longueur + 1)
     Dim Plages As Object
     Set Plages = oClasseur.createInstance("com.sun.star.sheet.SheetCellRanges")
     Dim index As Integer
     index = 0
     Dim Signal1() As Variant
     Dim FirstArray(1)
     ReDim Signal1(Longueur - 1)
     Dim Signal As Variant
     Signal = Array(FirstArray, Signal1)
     T3 = Timer
     Signal = PlageCellules.getDataArray()
     T4 = Timer
     While index < Longueur
        Set Cellule = oFeuille.getCellByPosition(0, index + 1)
        Signal1(index) = Cellule.getString()
        index = index + 1
     Wend
     T5 = Timer
     Debug.Print "Initialisation : " & (T1 - T)
     Debug.Print "Ouverture Classeur : " & (T2 - T1)
     Debug.Print "Initialisation variables : " & (T3 - T2)
     Debug.Print "Lecture par tableaux : " & (T4 - T3)
     Debug.Print "Lecture cellule par cellule : " & (T5 - T4)
        'Ferme le document
     oClasseur.Close (True)
     Set oClasseur = Nothing
    End Sub
     
    Function setOOoProp(oSM, cName, uValue) As Object
     
      Dim oPropertyValue As Object
     
      Set oPropertyValue = oSM.Bridge_GetStruct("com.sun.star.beans.PropertyValue")
      oPropertyValue.Name = cName
      oPropertyValue.Value = uValue
     
      Set setOOoProp = oPropertyValue
     
     
    End Function


    Le résultat est sans appel :


    La lecture par tableaux est nettement plus rapide !

    Attention on récupère un tableau de tableaux ( Signal) :



    Ami calmant, J.P
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  5. #5
    Membre du Club
    Geeeeeeenial. Un grand, grand merci je passe de 4.2s à 7ms pour une boucle de 9300 elements...

    Existe il un equivalenet pour l'ecriture ? SetArray() ?

    J'ai essayé ça mis non

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
                Dim PlageCellules As Object = MySheet.getCellRangeByName("A2:A7")
                Dim Plages As Object = MyDocument.createInstance("com.sun.star.sheet.SheetCellRanges")
                Dim Signal_temp1(5, 1) As Object
                Signal_temp1(0, 0) = 1
                Signal_temp1(1, 0) = 2
                Signal_temp1(2, 0) = 3
                Signal_temp1(3, 0) = 4
                Signal_temp1(4, 0) = 5
     
                PlageCellules.setDataArray(Signal_temp1)


    J'ai aussi essayé ça

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
                Dim Signal_temp1(5, 1) As Object
     
                Dim idx As Integer = 0
                For idx = 0 To 5
                    Dim FirstArray(0) As Object
                    FirstArray(0) = idx + 1
                    Signal_temp1(idx, 0) = FirstArray(0)
                Next
     
     
                PlageCellules.setDataArray(Signal_temp1)

  6. #6
    Membre du Club
    Bon j'ai réussi

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
                Dim Signal_temp1(5) As Object
     
                Dim idx As Integer = 0
                For idx = 0 To 5
                    Dim FirstArray(0) As Object
                    FirstArray(0) = idx + 1
                    Signal_temp1(idx) = FirstArray
                Next
     
     
                PlageCellules.setDataArray(Signal_temp1)


    Encore merci pour ton aide

  7. #7
    Membre du Club
    Pour le service manager, impossible d'optimiser ?

  8. #8
    Expert confirmé
    hello,
    à mon avis c'est parce que LibreOffice n'est pas déjà chargé en mémoire. Exécutes la macro plusieurs fois et regarde si le service manager est plus rapide à se créer après la première fois. Si c'est le cas
    charge LibreOffice au démarrage du système :



    Ami calmant, J.P
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  9. #9
    Membre chevronné
    Pas besoin de sortir l'artillerie lourde pour lire de l'ODF :
    http://beaussier.com/sections/viewto...f=7&t=1583
    Rédacteur PHP / Delphi ADO / Novell / OpenOffice.org

    Inutile de m'envoyer vos questions par MP, je ne réponds que par le forum.

  10. #10
    Membre du Club
    Merci à vous deux.

    Jurassic pork, c'est effectivement plus rapide mais lorsque j'essaye d'ouvrir une seconde fois je ne peux pas. Si je regarde dans les processus, j'ai LibreOffice qui reste alors que je fais un kill.
    Avant de cocher cette case, je n'avais plus de processus ouvert et je pouvais ouvrir un second fichier.
    Du coup en cochant cette option ça marche, mais je pense que je dois modifier quelque chose dans mon code !?

    Bidouille, merci pour le lien. Pour le moment je ne vais pas tout casser car je suis assez en retard sur mon projet mais je vais regarder attentivement pour le prochain ca je travaille souvent avec libreoffice.

  11. #11
    Membre du Club
    Apparemment le soucis viendrait qu'il y ai plusieurs instances et qu'il faut récupérer l'instance en cours si elle existe.
    Je cherche du côté de Dim OO As XComponentContext = uno.util.Bootstrap.bootstrap() mais j'ai du mal à comprendre le fonctionnement

    J'ai ce code là mais je n'arrive pas à aller plus loin pour charger mondocument. Le loader retourné correspond à quoi ? Comment lui passer mon chemin de fichier ?

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        Private Shared Function LoadOO() As XComponentLoader
     
            Try
                Dim OO As XComponentContext = uno.util.Bootstrap.bootstrap()
                Dim oServMan As XMultiServiceFactory = OO.getServiceManager()
                Dim aLoader As XComponentLoader = oServMan.createInstance("com.sun.star.frame.Desktop")
                Return aLoader
            Catch ex As Exception
                Return Nothing
            End Try
     
     
        End Function

  12. #12
    Expert confirmé
    hello,
    Citation Envoyé par touf26 Voir le message
    Merci à vous deux.

    Jurassic pork, c'est effectivement plus rapide mais lorsque j'essaye d'ouvrir une seconde fois je ne peux pas. Si je regarde dans les processus, j'ai LibreOffice qui reste alors que je fais un kill.
    Avant de cocher cette case, je n'avais plus de processus ouvert et je pouvais ouvrir un second fichier.
    Du coup en cochant cette option ça marche, mais je pense que je dois modifier quelque chose dans mon code !?
    je n'ai pas ton problème : fermes-tu bien ton classeur en fin d'utilisation ?

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    'Ferme le document 
      MyDocument.Close (True)
     Set  MyDocument = Nothing


    Ami calmant, J.P
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  13. #13
    Membre du Club
    Non effectivement j'avais uniquement un

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Desktop.terminate()


    En ajoutant le document.close ça fonctionne correctement.

    Et bien merci pour tout là c'est bien rapide

###raw>template_hook.ano_emploi###