[[Résolu][Calc] Diagramme (Charts) : Changer plage catégorie

Discussions et questions sur tout ce qui concerne la programmation tous langages et tous modules confondus.

Modérateur : Vilains modOOs

Règles du forum
:alerte: Balisage obligatoire dans cette section !
Aidez-nous à vous aider au mieux en balisant correctement votre question : reportez-vous sur les règles de cette section avant de poster !
ThierryM
Membre enthOOusiaste
Membre enthOOusiaste
Messages : 437
Inscription : 26 nov. 2006 12:29
Localisation : Les Corbières
Contact :

[[Résolu][Calc] Diagramme (Charts) : Changer plage catégorie

Message par ThierryM »

Adieu a totes,
Je me casse actuellement les dents pour mettre à jour un graphique complexe (avec des couleurs de remplissage "Fill Color") pour lequel je change de plages de données via des macros.
Pour un graphique simple, je n'ai pas de problème en changeant les différentes plages via la propriété "Ranges".
Par contre dès que le diagramme se complexifie (plage pour couleurs de remplissage, titre non contigu), cette façon de procéder ne marche plus et il faut passer par des macros plus élaborées (voir ce sujet où j'en parlais déjà : https://forum.openoffice.org/fr/forum/v ... =8&t=59257).
Je vous joins un fichier reprenant les différentes macros ainsi que les différents diagrammes :
  • La première feuille contient les données en ligne à traiter
  • La deuxième contient un graphique simple que j'actualise en fonction d'une date de début et d"une date de fin, via une première macro qui ne pose pas de problème : tout fonctionne correctement
  • La troisième feuille est un graphique complexe obtenu manuellement.
  • La quatrième feuille reprend la structure du troisième graphique mais je veux modifier les plages de données en fonction d'une date de début et d'une date de fin : il y a 2 macros associées (la première ne fonctionnant pas et la seconde non plus sauf si on ne change pas les catégories avec la propriétés "Ranges" (le code est commenté).
Capture du diagramme
Capture du diagramme
Voici le code de toutes les macros :

Code : Tout sélectionner

REM  *****  BASIC  *****

Sub MAJHistogrammeJourEcole 'Macro fonctionnant très bien
'Macro permettant de mettre à jour le graphique du taux de présences journalier
' en fonction des dates de début et de fin d'observation
 monClasseur=thisComponent
 fData=monClasseur.Sheets.getByName("Recueil Stats")
 nomEcole=fData.getCellRangeByName("A4").String
 fGraphique=monClasseur.Sheets.getByName("Histogramme Journées École")
 dateDeb=fGraphique.getCellRangeByName("B1").String
 dateFin=fGraphique.getCellRangeByName("F1").String
 premiereColonneDates=fGraphique.getCellRangeByName("D1").Value
 derniereColonneDates=fGraphique.getCellRangeByName("H1").Value
 ch1=fGraphique.Charts(0)
 plages1=ch1.getRanges
 plageDates=plages1(0)
 plageDates.StartColumn=premiereColonneDates
 plageDates.EndColumn=derniereColonneDates
 plages1(0)=plageDates
 plageNom=plages1(1)
 plageValeurs=plages1(2)
 plageValeurs.StartColumn=premiereColonneDates
 plageValeurs.EndColumn=derniereColonneDates
 plages1(2)=plageValeurs
 ch1.setRanges(plages1())

 diag1=fGraphique.Charts(0).EmbeddedObject
 diag1.Title.String= "Taux de présence journalier de l'école " & nomEcole & " du " & dateDeb & " au " & dateFin
 'xray diag1
End Sub

Sub MAJHistogrammeDemiJourEcole 'NE MARCHE PAS !!!
'Macro permettant de mettre à jour le graphique du taux de présences par demi-journées
' en fonction des dates de début et de fin d'observation
 monClasseur=thisComponent
 fData=monClasseur.Sheets.getByName("Recueil Stats")
 nomEcole=fData.getCellRangeByName("A4").String
 fGraphique=monClasseur.Sheets.getByName("Histogramme Demi Journées École_2")
 dateDeb=fGraphique.getCellRangeByName("B1").String
 dateFin=fGraphique.getCellRangeByName("F1").String
 premiereColonneDates=fGraphique.getCellRangeByName("D1").Value
 derniereColonneDates=fGraphique.getCellRangeByName("H1").Value
 ch=fGraphique.Charts(0)
 plages=ch.getRanges
 xray plages
 'exit sub
 'plageCouleurs=plages(0)
 'plageCouleurs.StartColumn=premiereColonneDates+1
 'plageCouleurs.EndColumn=derniereColonneDates+1
 'plages(0)=plageCouleurs
 plageDates=plages(0)
 plageDates.StartColumn=premiereColonneDates+2
 plageDates.EndColumn=derniereColonneDates+1
 plages(0)=plageDates 
 plageNom=plages(1)
 plageValeurs=plages(2)
 plageValeurs.StartColumn=premiereColonneDates+2
 plageValeurs.EndColumn=derniereColonneDates+1
 plages(2)=plageValeurs
 xray plages
 ch.setRanges(plages())

 diag1=fGraphique.Charts(0).EmbeddedObject
 diag1.Title.String= "Taux de présence par demi-journées de l'école " & nomEcole & " du " & dateDeb & " au " & dateFin & " (matin en vert, après-midi en jaune)"
 'xray diag1
End Sub


'------------------------------------------------------------------------------------------------------------------------------------------------------------
REM  *****  BASIC  *****
'Macros trouvée ici : https://ask.libreoffice.org/en/question/75127/macro-change-categories-data-range/
'Permet de mettre à jour les diagrammes
' Macro adaptée pour des données en ligne

Sub UpdateDocChartRanges
 monClasseur=thisComponent
 fData=monClasseur.Sheets.getByName("Recueil Stats")
 nomEcole=fData.getCellRangeByName("A4").String
 fGraphique=monClasseur.Sheets.getByName("Histogramme Demi Journées École_2")
 dateDeb=fGraphique.getCellRangeByName("B1").String
 dateFin=fGraphique.getCellRangeByName("F1").String
 premiereColonneDates=fGraphique.getCellRangeByName("D1").Value
 derniereColonneDates=fGraphique.getCellRangeByName("H1").Value
 ch=fGraphique.Charts(0)
 'xray ch.EmbeddedObject
 'Replace chart datasequences of chart series      
 UpdateChartRanges( ch, premiereColonneDates, derniereColonneDates-1)
End Sub

Sub UpdateChartRanges( oChart As Object, iFirstColumn As Long, iLastColumn As Long )

   Dim oChartDoc As Object
   
   Dim oDataProvider As Object
   Dim oCooSys As Object
   Dim oCoods As Object
   Dim oChartTypes As Object
   Dim oChartType As Object
   Dim oDataSeriesList As Variant
   
   Dim oDataSequence As Object
   Dim oValues As Object
   Dim oNewDataSeries() As Object
   Dim oSequenceY As Object
   Dim oSequenceLabel As Object
   
   Dim i As Integer
   Dim n As Integer
   
   Dim bCategories As Boolean
   
   Dim il As Integer
   Dim iu As Integer
   Dim vSequences() As Object
   Dim bFirstColumnLabel As Boolean
   Dim oRange As Object

   oChartDoc = oChart.EmbeddedObject
   
   oDataProvider = oChartDoc.getDataProvider()
   
   oCooSys = oChartDoc.getFirstDiagram().getCoordinateSystems()
   oCoods = oCooSys(0) ' this chart has only a coordinate system
   
   oChartTypes = oCoods.getChartTypes() ' chart type one by one
   oChartType = oChartTypes(0)
   
   ' all data series belongs the chart type
   oDataSeriesList = oChartType.getDataSeries()
   
   ' Save and then disable categories so we can treat them as series and restore later
   bCategories = oChartDoc.DataSourceLabelsInFirstRow
      
   ' Record if first row is label
   'bFirstColumnLabel = oChartDoc.DataSourceLabelsInFirstColumn
      
   ReDim oNewDataSeries(lbound(oDataSeriesList) To ubound(oDataSeriesList)) As Object
   
   ' For each series in the chart
   For i = lbound(oDataSeriesList) To ubound(oDataSeriesList)
      ' create new DataSeries
      oNewDataSeries(i) = CreateUnoService("com.sun.star.chart2.DataSeries")
      
      ' Copy the existing formatting of this series
      oNewDataSeries(i) = oDataSeriesList(i)
      
      il = lbound(oNewDataSeries(i).DataSequences)
      iu = ubound(oNewDataSeries(i).DataSequences)
      
      ReDim vSequences(il To iu) As Object
      
      ' Update each data sequence in each series
      For n = il To iu
         oDataSequence = oNewDataSeries(i).DataSequences(n)
         'xray oDataSequence
         
         vSequences(n) = CreateUnoService("com.sun.star.chart2.data.LabeledDataSequence")

         oSequenceY = CreateDataSequence(oDataProvider, _
                                 UpdateSeriesRange( oDataSequence.Values.SourceRangeRepresentation, iFirstColumn, iLastColumn ), _
                                 oDataSequence.Values.Role)
         'xray oSequenceY
         If NOT IsNull(oSequenceY) Then
            vSequences(n).setValues(oSequenceY)
            
            If NOT IsNull(oDataSequence.Label) Then
               oSequenceLabel = CreateDataSequence(oDataProvider, oDataSequence.Label.SourceRangeRepresentation, "")
         'xray oSequenceLabel
               
               vSequences(n).setLabel(oSequenceLabel) ' label is used as name
            End If
         End If
      Next n
      oNewDataSeries(i).setData(vSequences)
   Next i
 
 ' ******** PARTIE PROBLÉMATIQUE concernant le changement de plage pour la catégorie  
   If bCategories Then
      '   Change the range of the category data
      print iFirstColumn, iLastColumn    
      plages = oChart.Ranges
      plageCateg=plages(0)
      plageCateg.StartColumn = iFirstColumn
      plageCateg.EndColumn = iLastColumn
      plages(0)=plageCateg
      xray plages
      '   Set the new category data range in the chart data range
      oChart.Ranges = plages
  '  ********************************************    
      '   Put the data series back in the chart
      oChartType.DataSeries = oNewDataSeries
   End If
   
End Sub

Function UpdateSeriesRange( ByRef sRange As String, iFirstColumn As Long, iLastColumn As Long ) As String
   Dim sUpdateSeriesRange As String
   Dim iFeuille As Integer, plageMAJ As Object
   
  ' print sRange
   'Récupère le nom de la feuille
   iFeuille=InStr(sRange,".")
   nomFeuille=Mid(sRange,3,iFeuille-4)
   'Traduit l'AbsoluteNAme de la plage en plage de cellules
   plageDepart=thisComponent.Sheets.getByName(nomFeuille).getCellRangeByName(sRange)
   nFeuille=plageDepart.RangeAddress.Sheet
   ligneDepart=plageDepart.RangeAddress.StartRow
   colonneDepart=iFirstColumn
   ligneArriv=plageDepart.RangeAddress.EndRow
   colonneArriv=iLastColumn
   plageMAJ=thisComponent.Sheets(nFeuille).getCellRangeByPosition(colonneDepart,ligneDepart,ColonneArriv,LigneArriv)
   'xray plageMAJ'.RangeAddress
 '  print plageMAJ.AbsoluteName
   sUpdateSeriesRange = plageMAJ.AbsoluteName
   UpdateSeriesRange = sUpdateSeriesRange
End Function

Function CreateDataSequence( _
   oDataProvider As Object, _
   sRangeRepresentation As String, sRole As String ) As Object

'   Based on post by Hanya
'   https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=8991#p46467

' creat new DataSequence from range representaion
' that provides real data and its role in the series
' oDataProvider: com.sun.star.chart2.data.XDataProvider
' sRangeRepresentation: range address e.g. Sheet1.A1:B2
' sRole: role is defined in com.sun.star.chart2.data.DataSequenceRole

   Dim oDataSequence As Object
   
   On Error GoTo Handler
   ' create .chart2.data.DataSequence from range representation
   oDataSequence = oDataProvider.createDataSequenceByRangeRepresentation(sRangeRepresentation)

   If NOT IsNull(oDataSequence) Then
      oDataSequence.Role = sRole
   End If
   
Handler:
   CreateDataSequence = oDataSequence
End Function
J'ai tourné en long, en large et en travers mais sans résultat. Auriez-vous des solutions, ou savez-vous ce qui m'échappe ?
En vous remerciant pour vos éclairages, cordialement,

Thierry
Pièces jointes
Actualisation_Graphique.ods
Fichier Calc contenant toutes les macros et les différents diagrammes
(40.05 Kio) Téléchargé 106 fois
Dernière modification par ThierryM le 12 avr. 2019 23:53, modifié 1 fois.
LibreOffice Version: 7.6.2 / Linux Mint Mate Edition 21.2 / Pourquoi privilégier les formats de fichiers ouverts ?
Avatar de l’utilisateur
OOotremer971
ManitOOu
ManitOOu
Messages : 2744
Inscription : 16 avr. 2010 15:31

Re: [Calc] Diagramme (Charts) : Changement plage catégorie

Message par OOotremer971 »

Bonjour,

Le temps de trouver une vrai solution, qui ne paraît pas simple au premier abord, tu peux te simplifier la vie en masquant (par macro) les colonnes non concernées par la zone à afficher. Le graphique s'actualise instantanément sans rechigner :lol:

Je dis ça juste pour te faire patienter le temps de trouver une vraie solution, à savoir créer un graphique de toutes pièces à partir de plages de données connues.

A+
En principe, toujours à jour des dernières versions dites stables
AOO
LibreOffice
Debian 10 et 11
ThierryM
Membre enthOOusiaste
Membre enthOOusiaste
Messages : 437
Inscription : 26 nov. 2006 12:29
Localisation : Les Corbières
Contact :

Re: [Calc] Diagramme (Charts) : Changement plage catégorie

Message par ThierryM »

Adieu,
Merci OOotremer971 de te pencher sur le problème.
Effectivement le masquage est une bonne solution de contournement :wink: et ça peut permettre de synchroniser tous les graphiques en même temps aussi d'une façon facile.
Par contre, je suis curieux de connaître la solution :D qui permettra de mieux comprendre comment sont gérés les graphiques.
Cordialement,

Thierry
LibreOffice Version: 7.6.2 / Linux Mint Mate Edition 21.2 / Pourquoi privilégier les formats de fichiers ouverts ?
Avatar de l’utilisateur
OOotremer971
ManitOOu
ManitOOu
Messages : 2744
Inscription : 16 avr. 2010 15:31

Re: [Calc] Diagramme (Charts) : Changement plage catégorie

Message par OOotremer971 »

ThierryM a écrit :Par contre, je suis curieux de connaître la solution :D qui permettra de mieux comprendre comment sont gérés les graphiques.
Oui moi aussi, j'ai bien l'intention de lui tordre le cou, mais à moins de trouver un code exemple déjà tout fait, cela risque de prendre un peu de temps libre dont je ne dispose pas en ce moment.

Un exemple pour faire mumuse :
J'ai créé une feuille Recueil Stats_2(masquée) liée à la feuille Recueil Stats par le menu Feuille>Insertion à partir d'un fichier au cas où la feuille Recueil Stats devrait rester en l'état pour afficher d'autres diagrammes.

Le code est dans le module1

A+
Pièces jointes
Actualisation_Graphique_Mod1.ods
(55.6 Kio) Téléchargé 105 fois
En principe, toujours à jour des dernières versions dites stables
AOO
LibreOffice
Debian 10 et 11
ThierryM
Membre enthOOusiaste
Membre enthOOusiaste
Messages : 437
Inscription : 26 nov. 2006 12:29
Localisation : Les Corbières
Contact :

Re: [Calc] Diagramme (Charts) : Changement plage catégorie

Message par ThierryM »

Merci OOotremer971 pour ton travail.
Ma feuille "Recueil Stats" originale est une feuille obtenue automatiquement via des macros qui vont chercher les informations dans différents classeurs (1 classeur par classe). Du coup, les plages des dates sont des plages nommées ce qui me permet facilement de travailler (masquer/afficher) sur leurs colonnes (ce n'est pas le cas dans le fichier que j'ai posté qui est une version simplifiée).
Je suppose que la feuille masquée "Recueil Stats_2" est une feuille liée à "Recueil Stats" (d'où l'insertion via le menu "Feuille -> Insertion à partir d'un fichier") de façon à ce que toutes les modifs dans la feuille source se répercutent sur cette deuxième feuille. Je pense qu'il y a une erreur de liaison car à l'ouverture si j'actualise le graphique disparaît. En fait les noms de feuilles liées ne correspondent pas.
Je vais donc adopter ce contournement (ce qui ne signifie pas que mon problème soit résolu :wink:).
Cordialement,

Thierry
LibreOffice Version: 7.6.2 / Linux Mint Mate Edition 21.2 / Pourquoi privilégier les formats de fichiers ouverts ?
Avatar de l’utilisateur
OOotremer971
ManitOOu
ManitOOu
Messages : 2744
Inscription : 16 avr. 2010 15:31

Re: [Calc] Diagramme (Charts) : Changement plage catégorie

Message par OOotremer971 »

ThierryM a écrit :Je pense qu'il y a une erreur de liaison car à l'ouverture si j'actualise le graphique disparaît.
Sûrement un problème de chemin sous des os différents ?

J'ai supprimé le lien et affiché la feuille Recueil Stats_2 juste pour que tu puisses tester à nouveau. Chez moi ça marche nickel c'est bluffant.

A+
Pièces jointes
Actualisation_Graphique_Mod2.ods
(62.05 Kio) Téléchargé 96 fois
En principe, toujours à jour des dernières versions dites stables
AOO
LibreOffice
Debian 10 et 11
ThierryM
Membre enthOOusiaste
Membre enthOOusiaste
Messages : 437
Inscription : 26 nov. 2006 12:29
Localisation : Les Corbières
Contact :

Re: [Calc] Diagramme (Charts) : Changement plage catégorie

Message par ThierryM »

Merci (ta version précédente marchait si on n'actualisait pas à l'ouverture).
Bonne idée, le coup de la validité des cellules pour les dates (en fait, j'avais laissé les plages nommées dans le fichier exemple) : j'achète :wink: .
Cordialement,

Thierry
LibreOffice Version: 7.6.2 / Linux Mint Mate Edition 21.2 / Pourquoi privilégier les formats de fichiers ouverts ?
Avatar de l’utilisateur
Hubert Lambert
SuppOOrter
SuppOOrter
Messages : 1214
Inscription : 06 avr. 2016 09:26

Re: [Calc] Diagramme (Charts) : Changement plage catégorie

Message par Hubert Lambert »

Bonjour,

Ci-joint un exemple qui illustre comment modifier les données du diagramme, inspiré par les différents fils mentionnés dans les commentaires du code original.
Le même code fonctionne pour les deux diagrammes du documents :

Code : Tout sélectionner

Sub MAJHistogrammeJourEcole
    'Macro permettant de mettre à jour le graphique du taux de présences journalier
    ' en fonction des dates de début et de fin d'observation
    monClasseur = thiscomponent
    fData=monClasseur.Sheets.getByName("Recueil Stats")
    fGraphique = monClasseur.CurrentController.ActiveSheet
    nomEcole=fData.getCellRangeByName("A4").String
    dateDeb=fGraphique.getCellRangeByName("B1").String
    dateFin=fGraphique.getCellRangeByName("F1").String
    premiereColonneDates=fGraphique.getCellRangeByName("D1").Value -1
    derniereColonneDates=fGraphique.getCellRangeByName("H1").Value -1
    ch1=fGraphique.Charts(0)
    diag1=fGraphique.Charts(0).EmbeddedObject
    diagram = diag1.FirstDiagram
    dataprovider = diag1.DataProvider
    coordsys = diagram.CoordinateSystems(0)

    REM données
    charttype = coordsys.ChartTypes(0)
    dataserie = charttype.DataSeries(0)
    datasequences = dataserie.DataSequences
    dim newsequences(ubound(datasequences))
    for n = 0 to ubound(datasequences)
        seq = datasequences(n)
        values = seq.Values
        r = fData.getCellRangeByName(values.SourceRangeRepresentation).RangeAddress
        newrepr = fData.getCellRangeByPosition(premiereColonneDates, r.StartRow, derniereColonneDates, r.EndRow).AbsoluteName
        newvalues = dataprovider.createDataSequenceByRangeRepresentation(newrepr)
        newvalues.Role = values.Role
        newvalues.IncludeHiddenCells = values.IncludeHiddenCells
        newseq = CreateUnoService("com.sun.star.chart2.data.LabeledDataSequence")
        newseq.Label = seq.Label
        newseq.Values = newvalues
        newsequences(n) = newseq
    next n

    REM étiquettes axe X
    xaxis = coordsys.getAxisByDimension(0,0)
    scaledata = xaxis.ScaleData
    cat = scaledata.Categories
    values = cat.Values
    r = fData.getCellRangeByName(values.SourceRangeRepresentation).RangeAddress
    newrepr = fData.getCellRangeByPosition(premiereColonneDates, r.StartRow, derniereColonneDates, r.EndRow).AbsoluteName
    newvalues = dataprovider.createDataSequenceByRangeRepresentation(newrepr)
    newvalues.Role = values.Role
    newvalues.IncludeHiddenCells = values.IncludeHiddenCells
    newcat = CreateUnoService("com.sun.star.chart2.data.LabeledDataSequence")
    newcat.Label = cat.Label
    newcat.Values = newvalues
    dataserie.setData(newsequences)
    scaledata.Categories = newcat
    xaxis.setScaleData(scaledata)

    REM Titre
    diag1.Title.String= "Taux de présence journalier de l'école " & nomEcole & " du " & dateDeb & " au " & dateFin
End Sub

Cordialement :wink: .
Pièces jointes
Actualisation_Graphique.ods
(38.5 Kio) Téléchargé 174 fois
AOOo 4.1.7 sur Win10
AOOo 4.1.x sur Linux Mint
LibreOffice 5.x/6.x sur Linux Mint
--
| « Nos défauts devraient nous donner une qualité : l'indulgence pour les défauts des autres » (Rivarol)
ThierryM
Membre enthOOusiaste
Membre enthOOusiaste
Messages : 437
Inscription : 26 nov. 2006 12:29
Localisation : Les Corbières
Contact :

Re: [Calc] Diagramme (Charts) : Changement plage catégorie

Message par ThierryM »

Adieu,
Chapeau bas Hubert !!!
Ça marche super bien. En plus le fait d'avoir utilisé un événement de feuille pour rendre l'affichage instantanée (plus besoin de bouton pour actualiser) est un plus indéniable.
Je n'ai pas eu le temps de trop regarder le code mais je le fais dès que je peux.
Un grand merci à vous, Hubert et Ootremer971 pour vos apports précieux.
Bien cordialement,
Thierry
LibreOffice Version: 7.6.2 / Linux Mint Mate Edition 21.2 / Pourquoi privilégier les formats de fichiers ouverts ?
Avatar de l’utilisateur
OOotremer971
ManitOOu
ManitOOu
Messages : 2744
Inscription : 16 avr. 2010 15:31

Re: [[Résolu][Calc] Diagramme (Charts) : Changer plage catég

Message par OOotremer971 »

Bonjour,
ThierryM a écrit :Chapeau bas Hubert !!!
Je tiens moi z'aussi à t’adresser mes congratulations...je n'ai pas encore décortiqué la bête mais à première vue je n'y serais pas arrivé seul.
:bravo: :super:
A+
En principe, toujours à jour des dernières versions dites stables
AOO
LibreOffice
Debian 10 et 11
Verrouillé