[Résolu][Calc] Remplacer une source odb depuis un classeur

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 !
Frédérick
Membre lOOyal
Membre lOOyal
Messages : 49
Inscription : 05 déc. 2017 14:17

[Résolu][Calc] Remplacer une source odb depuis un classeur

Message par Frédérick »

Bonjour ou bonsoir à tous

Sur le modèle du suprême proposé par Dude ici : https://forum.openoffice.org/fr/forum/v ... =15&t=6872 et dans la lignée de ce message là : https://forum.openoffice.org/fr/forum/v ... =8&t=57294, je souhaite non pas créer une source de données mais la remplacer de manière automatique en utilisant le classeur courant comme source.

Mon code modifié est donc le suivant :

Code : Tout sélectionner

Sub ActualiserSource(vSource as String, vChemin as String)

	Dim vBase as string
	Dim vContexte, vSrcODB as Object
	
	vBase = vChemin & vSource & ".odb"
	
	' on vérifie que la source est déclarée et, dans ce cas, on casse le lien
	vContexte = createUnoService("com.sun.star.sdb.DatabaseContext")
	If vContexte.hasByName(vSource) Then
		vContexte.revokeObject(vSource)
	end if

	' désormais, la source n'est plus enregistrée, on recrée le lien avec le fichier Base (.odb)
	' la création du lien va forcer l'actualisation de la source
	vSrcODB = createUnoService("com.sun.star.sdb.DataSource")
	vBase = ConvertToURL(vChemin)
	vSrcODB.DatabaseDocument.storeAsURL(vBase & vSource & ".odb", Array())
	vBase = "sdbc:calc:" & thisComponent.geturl()
	vContexte.registerObject(vSource, vSrcODB)
	vSrcODB.setPropertyValue("URL", vBase)
	vSrcODB.DatabaseDocument.store()
   
end sub
Si je viens d'ouvrir mon tableur, lors d'une première exécution, pas de soucis. Par contre, si je réitère l'opération dans la même session, j'ai le message en pièce jointe.
Il semble qu'il y ait un problème d'accès à ma base odb, ce qui est confirmé quand je tente de renommer à la main ce fichier, renommage bloqué car le fichier est ouvert dans libreoffice (ce qui doit être en arrière plan puisque je n'ai pas la vue sur ce fichier)
Y-a-t'il moyen, après avoir révoqué la base, d'en forcer la fermeture alors que je ne l'ai jamais nulle part explicitement ouverte ?
Dans le cas contraire, y-a-t'il moyen de forcer le remplacement ?

Au pire, j'envisage de lancer ce code à l'ouverture du document, ce qui fera le boulot, mais je dois avouer que j'aimerai bien comprendre la raison et l'éventuelle parade à ce blocage pour toute éventualité future et pour la compréhension des principes.

Merci de votre aide

Cordialement

Frédérick
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par Frédérick le 24 avr. 2018 15:58, modifié 3 fois.
Windows 7
LibreOffice 4.3.7.2
Et en plus, on ne m'a pas demandé mon avis :-(
Denis_21
Membre lOOyal
Membre lOOyal
Messages : 43
Inscription : 04 août 2017 08:08

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Denis_21 »

Voir si le code en https://forum.openoffice.org/fr/forum/v ... ebbdc3c4d1
peux fonctionner dans votre cas

Cordialement
LibreOffice Version: 6.0.7.3 (x64)
Win 7 Professionnel
Avatar de l’utilisateur
Hubert Lambert
SuppOOrter
SuppOOrter
Messages : 1214
Inscription : 06 avr. 2016 07:26

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Hubert Lambert »

Bonjour,

Cela devrait fonctionner en ne modifiant que l'url de l'objet "DataSource" :

Code : Tout sélectionner

sub ActualiserSource(vSource as String)
    vContexte = createUnoService("com.sun.star.sdb.DatabaseContext")
    vSrcODB = vContexte.getByName(vSource)
    vBase = "sdbc:calc:" & thiscomponent.URL
    vSrcODB.URL = vBase
end sub
Cordialement.
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)
Frédérick
Membre lOOyal
Membre lOOyal
Messages : 49
Inscription : 05 déc. 2017 14:17

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Frédérick »

Merci pour vos réponses.

Je n'aurais peut-être pas le temps de tester avant la semaine prochaine mais je reviens vers vous aussi vite que possible.

Hubert Lamnbert, je viens de faire le test de ta solution mais malheureusement sans succès. Même quand le odb n'est pas vérouillé, je n'arrive pas à remettre le lien vers le bon classeur.

Denis_21, je suis en train de regarder ce que je peux faire avec ta solution. Nous avons exactement le même besoin : créer le lien vers la bonne source de données de manière transparente pour l'utilisateur, quelque soit son poste de travail. Toutefois, ma source de données est sous Calc.
Par rapport à ta ligne :

Code : Tout sélectionner

cheminBdd = "sdbc:postgresql:host=xxxxxxxx dbname=favoris"
, j'ai à peu prêt le même code avec

Code : Tout sélectionner

vBase = "sdbc:calc:" & thisComponent.geturl()
mais tu rajoutes le nom de la source ensuite. Est-ce que ça apporte quelque chose ? Je n'ai vu aucun changement moi.[/raye] Je suis bête, c'est la base dans ton sql et pas le nom de la source dans libreoffice.

Merci à vous deux.

Cordialement

Frédérick
Dernière modification par Frédérick le 05 avr. 2018 12:59, modifié 1 fois.
Windows 7
LibreOffice 4.3.7.2
Et en plus, on ne m'a pas demandé mon avis :-(
Frédérick
Membre lOOyal
Membre lOOyal
Messages : 49
Inscription : 05 déc. 2017 14:17

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Frédérick »

Bon, je continue à bosser sur ce sujet en pointiller en même temps que j'avance mes autres questions mais e tourne en rond et ça commence à m'obséder sérieusement.

Alors, histoire de vous expliquer ce que j'ai regardé depuis :

- le code bloque sur l'exécution de

Code : Tout sélectionner

vSrcODB.DatabaseDocument.storeAsURL(vBase & vSource & ".odb", Array())
avec le message en copie d'écran sur mon premier post.
- si je tente de modifier le nom ou l'extension du fichier odb dans Windows, j'obtiens le message en copie d'écran ci-dessous.
- si je fais un vSrcODB.isReadOnly, la réponse est false. Donc le document .odb n'est pas en lecture seule
- si j'applique le code ci-dessous qui permet de lister les documents ouverts dans libreoffice, la base odb n'y figure pas contrairement au message d'erreur de Windows !

Code : Tout sélectionner

	
vLesDocs = StarDesktop.components
	vLaCollection = vLesDocs.createEnumeration
	while vLaCollection.hasMoreElements
		vLeDoc = vLaCollection.nextElement
		msgbox "Fichier ouvert : " & vLeDoc.URL
	wend
Bref, le document n'est pas en lecture seule, n'est pas ouvert donc pas refermable, mais n'est pas modifiable.

Et donc, comme disait Leeloo : "please help"
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Windows 7
LibreOffice 4.3.7.2
Et en plus, on ne m'a pas demandé mon avis :-(
Avatar de l’utilisateur
Hubert Lambert
SuppOOrter
SuppOOrter
Messages : 1214
Inscription : 06 avr. 2016 07:26

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Hubert Lambert »

Frédérick a écrit :Hubert Lamnbert, je viens de faire le test de ta solution mais malheureusement sans succès. Même quand le odb n'est pas vérouillé, je n'arrive pas à remettre le lien vers le bon classeur.
Et pourtant ça tourne ! Testé sur Linux et Windows, avec le fichier odb fermé ou ouvert (ce qui n'a toutefois pas trop d'intérêt en l'espèce).
Pourrais-tu préciser exactement ce qui ne fonctionne pas ?
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)
Frédérick
Membre lOOyal
Membre lOOyal
Messages : 49
Inscription : 05 déc. 2017 14:17

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Frédérick »

Bonjour Hubert

Alors, voilà comment ça se passe :

Le principe déjà consiste à avoir un fichier de travail, le fichier Calc, à partir duquel je gère de nombreuses fonctionnalités. Parmi ces fonctionnalités, des remplissages automatiques de données à partir de source web, des envois automatiques de courriels via thunderbird ET 2 publipostages sur des modèles Writer. Les 2 publipostages utilisent la même source de données : le fichier Calc, en passant par le fichier odb éponyme, méthode habituelle de LibreOffice.
=> 4 fichiers :
- programmation.ods : la source de données Calc
- programmation.odb : le fichier LibreOffice Base qui fait le lien avec la source
- les 2 modèles Writer

Ce système est utilisé sur 4 sites différents avec chacun leur installation locale, chacun leur version de chacun des fichiers, et chacun un niveau informatique différent. En conséquence de quoi, je souhaite automatiser totalement la liaison avec la source de données en la déclarant à chaque ouverture du fichier source sous Calc qui est notre cœur de métier. Cela en prévision d'une éventuelle fausse manœuvre dont la conséquence serait la suppression de la source, ou un déplacement des fichiers. Le système marche parce que les fichiers sont chacun à leur place et les collègues ont parfois du mal à entendre qu'on ne peut pas déplacer des fichiers comme ça sans conséquence. Pour eux, c'est de la bureautique, c'est ouvert, et donc mettre sur C: ou sur un espace réseau c'est pareil. Et le déplacer n'a pas de conséquence. Quand ils perdent le raccourci de leur bureau, ils peuvent sans sourciller déplacer le fichier lui même pour le mettre sur le bureau. A l'inverse, quand un fichier est déplacé et qu'ils ont mis un raccourci, on a beau leur dire qu'il y a eu un déplacement, ils ne comprennent pas pourquoi le raccourci ne marche plus.

Bref, sur ces considérations quant à l'utilité du système, venons en au fonctionnement ou plutôt au dysfonctionnement :

- La macro de déclaration de la source de données odb est lancée à l'ouverture du fichier calc qui contient les données. Le plus souvent, tout marche sans soucis. Une fois de temps en temps, j'ai les erreurs décrites ci-dessus. Le code de cette macro est dans mon premier post de ce sujet.
- Si je lance à la main la macro de chargement ensuite, j'ai toujours les messages ci-dessus.
- Si j’inclus dans ma macro une vérification de lecture seule, la source odb n'est pas en lecture seule.
- Si j'inclus dans ma macro un listage des fichiers ouverts dans LibreOffice, la base odb n'y figure pas. Mais évidemment la source Calc si.
- Pourtant, la macro plante sur une IOException sur la ligne

Code : Tout sélectionner

vSrcODB.DatabaseDocument.storeAsURL(vBase & vSource & ".odb", Array())
- et quand ça plante, si je passe sous l'explorateur Windows, je ne peux pas (par exemple) renommer le fichier odb au motif qu'il est ouvert dans LibreOffice, ce qui est donc démenti par mon listage précédent

Je vais essayer de générer un fichier anonymisé pour reproduire le problème. Sinon, je peux te faire parvenir en MP mes fichiers réels. Le soucis c'est que dans mon appli réelle, j'ai largement dépassé les 1500 lignes de code et que ça devient compliqué de faire une extraction des seules fonctionnalités qui plantent.

Merci pour ton aide

Cordialement

Frédérick
Windows 7
LibreOffice 4.3.7.2
Et en plus, on ne m'a pas demandé mon avis :-(
Avatar de l’utilisateur
Hubert Lambert
SuppOOrter
SuppOOrter
Messages : 1214
Inscription : 06 avr. 2016 07:26

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Hubert Lambert »

Si je comprends bien, le principal problème est le déplacement du fichier odb.
Deux solutions a priori :
1. à la première installation, enregistrer l'odb à part, dans un répertoire "sûr" ;
2. dans ton code, plutôt que de révoquer la base si elle existe, insérer simplement mon code et ne créer le fichier odb que si le chemin n'existe pas déjà. Quelque chose comme ceci (à tester) :

Code : Tout sélectionner

    vContexte = createUnoService("com.sun.star.sdb.DatabaseContext")
    chemin = ConvertToURL(vChemin & vSource & ".odb")
    if vContexte.hasByName(vSource) then
        vSrcODB = vContexte.getByName(vSource)
        ' si le fichier odb existe, on se contente de
        ' modifier le lien vers le fichier Calc en cours
        if vSrcODB.DatabaseDocument.URL = chemin then
            vBase = "sdbc:calc:" & thiscomponent.URL
            vSrcODB.URL = vBase
            exit sub
        else
           ' sinon on (re)crée le fichier odb
            vContexte.revokeObject(vSource)
        end if
    end if
    vSrcODB = createUnoService("com.sun.star.sdb.DataSource")
    vSrcODB.DatabaseDocument.storeAsURL(chemin, Array())
    vBase = "sdbc:calc:" & thisComponent.geturl()
    vContexte.registerObject(vSource, vSrcODB)
    vSrcODB.setPropertyValue("URL", vBase)
    vSrcODB.DatabaseDocument.store()
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)
Frédérick
Membre lOOyal
Membre lOOyal
Messages : 49
Inscription : 05 déc. 2017 14:17

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Frédérick »

En fait, le problème n'est pas l'existence de l'odb. C'est que si le Calc a été déplacé alors l'odb conserve le lien vers l'emplacement précédent du Calc, qui n'est plus bon. D'où mon remplacement systématique.
D'ailleurs, la conséquence c'est que le message d'erreur de la macro, écrite sous Calc, indique un mauvais chemin vers l'ancienne adresse du fichier Calc. Moi, la première fois que j'ai eu ce message, je n'ai pas compris qu'il était en mémoire dans l'odb et j'ai longtemps cherché où je donnais ce chemin !

Mon problème de fond c'est que j'essaye de m'adapter aux conneries potentielles des utilisateurs et de les laisser faire en ayant un système assez souple pour compenser. Le changement de système les perturbe déjà, si en plus j'impose un truc trop dirigiste, va falloir gérer la mauvaise humeur. Mais je pense que si je n'arrive pas rapidement maintenant à trouver une solution, je vais m'orienter vers un contrôle du bon emplacement de la source avec message d'erreur et rappel à l'ordre à l'ouverture du fichier en cas de changement.
Windows 7
LibreOffice 4.3.7.2
Et en plus, on ne m'a pas demandé mon avis :-(
Avatar de l’utilisateur
Hubert Lambert
SuppOOrter
SuppOOrter
Messages : 1214
Inscription : 06 avr. 2016 07:26

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Hubert Lambert »

Ok, et donc quid de la solution proposée ci-dessus ?
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)
Frédérick
Membre lOOyal
Membre lOOyal
Messages : 49
Inscription : 05 déc. 2017 14:17

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Frédérick »

Bonjour Hubert (et bonjour tous les autres).

Je viens de tester ta solution avec exactement les mêmes résultats que la mienne. Encore une fois, le programme plante sur le StoreAsURL car le fichier semble être considéré comme étant ouvert, ce qui n'est pas confirmé par la liste des fichiers ouverts justement.

J'ai donc pour le moment contourné le problème. Je vérifie que le lien vers la source calc enregistré dans la base odb est à la bonne adresse. Si oui, pas de soucis, si non, alors je demande à l'utilisateur de tout refermer puisque mes fonctions marchent au premier chargement.

Code : Tout sélectionner

	
        vSource = "Programmation"
	vContexte = createUnoService("com.sun.star.sdb.DatabaseContext")
	If vContexte.hasByName(vSource) Then
		vSrcODB = vContexte.getByName(vSource)
		if ConvertToURL(mid(vSrcODB.URL, 11)) <> thisComponent.URL then
			' la source est déclarée mais pas avec le bon fichier ods
			vContexte.revokeObject(vSource)
			vFaireRecharge = true
		end if
	Else
		vFaireRecharge = true
	end if
	
	if vFaireRecharge then
	
		On Error GoTo GestErr
		
			msgbox "besoin de faire le rechargement"
			vSrcODB = createUnoService("com.sun.star.sdb.DataSource")
			vBase = ConvertToURL(getRepModeles)
			vSrcODB.DatabaseDocument.storeAsURL(vBase & vSource & ".odb", Array())
			vBase = "sdbc:calc:" & thisComponent.geturl()
			vContexte.registerObject(vSource, vSrcODB)
			vSrcODB.setPropertyValue("URL", vBase)
			vSrcODB.DatabaseDocument.store()
			
		GestErr:
			
			vMessage = "Attention, la source de données a été déplacée." & chr$(10)
			vMessage = vMessage & "Pour pouvoir la recharger correctement il faut fermer ce fichier et le relancer" & chr$(10) & chr$(10)
			vMessage = vMessage & "Il sera impossible d'utiliser les fonctions de publipostage sans cette opération."
			msgbox (vMessage , 48 + 0, "Source non trouvé")
			
	end if
En toute honnêteté, je ne vois pas trop en quoi ça résout le blocage. Par exemple, si je lance 2 fois de suite cette fonction, la première déclenche l'erreur, affiche le message, et pendant ce temps, la source est "révoquée". Le second envoi de la fonction passe alors sans soucis, sans que je ne ferme ni Calc ni quoi que ce soit.
Du coup, je me dis que le problème vient peut-être simplement d'une question de temporisation. Peut-être que le revoke prend du temps au cours duquel l'odb est occupé. J'essayerai quand j'aurais un peu plus de temps en rajoutant un delay à ma fonction initiale.

PS : et quand j'aurais fait ce dernier test, je baliserai résolu
Windows 7
LibreOffice 4.3.7.2
Et en plus, on ne m'a pas demandé mon avis :-(
Avatar de l’utilisateur
Hubert Lambert
SuppOOrter
SuppOOrter
Messages : 1214
Inscription : 06 avr. 2016 07:26

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Hubert Lambert »

J'ai fait de nombreux tests avec la version que je t'ai proposée, sans rencontrer jamais l'erreur que tu signales.
SI tu pouvais joindre une série de fichiers permettant de reproduire, ce serait plus simple et permettrait peut-être une solution plus propre...
Cordialement.
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)
Frédérick
Membre lOOyal
Membre lOOyal
Messages : 49
Inscription : 05 déc. 2017 14:17

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Frédérick »

Bonjour

Je n'ai finalement pas réussi à faire les tests que je voulais. trop de sujets urgents à traiter en plus de ce programme.
Je clos le sujet donc sans qu'il ne soit résolu.

Hubert, si tu es intéressé par mon code, je peux t'envoyer mon fichier réel par mail.

Merci de t'être penché sur mon problème.

Cordialement
Windows 7
LibreOffice 4.3.7.2
Et en plus, on ne m'a pas demandé mon avis :-(
Avatar de l’utilisateur
Bidouille
RespOOnsable forum
RespOOnsable forum
Messages : 12227
Inscription : 08 nov. 2005 16:23
Localisation : Caen, France

Re: [Calc] Remplacer une source odb depuis un classeur

Message par Bidouille »

Deux choses à retenir :

1) La balise [Résolu] se place au début du titre et non au milieu ou à la fin.
Frédérick a écrit :Hubert, si tu es intéressé par mon code, je peux t'envoyer mon fichier réel par mail.
2) Le principe d'un forum n'est pas de communiquer en privé des informations.
Il vous appartient de fournir un document anonymisé permettant de reproduire le dysfonctionnement exposé.
Frédérick
Membre lOOyal
Membre lOOyal
Messages : 49
Inscription : 05 déc. 2017 14:17

Re: [Résolu][Calc] Remplacer une source odb depuis un classe

Message par Frédérick »

remarque 1 : ok, j'ai changé l'ordre des balises
remarque 2 : je ne cherche plus à résoudre la question puisque j'ai mis résolu. Par contre, Hubert ayant travaillé sur le même genre de problématiques que moi mais n'ayant jamais eu le problème que je rencontre, je lui propose de lui refiler mon source complet pour qu'il regarde ce qui peut l'intéresser à titre perso. Et je ne vais donc pas m'amuser à faire un fichier anonymisé pour permettre à tout le monde de jouer avec mon code qui justement ne marche pas.
Quand j'aurais du temps (août), et sous réserve que ça intéresse du monde, pourquoi pas proposer des fichiers avec les différentes grandes fonctionnalités utilisées (mail, publipostage) mais pas dans l'immédiat.

Sinon, pour mon info perso, c'est quoi le lien entre toi et Dude car j'ai eu plusieurs réponse de ta part qui ont finalement été réattribuées à Dude. Alors du coup j'ai un peu de mal à suivre.
Windows 7
LibreOffice 4.3.7.2
Et en plus, on ne m'a pas demandé mon avis :-(