def process(PA): global ActiveWindow, Shapes, Word, TRs_all, xl, Visio global RESULTS try: # ouvrir le fichier excel et faire les initialisations de coutume xl = CreateObject("Excel.application") xl.Visible = False xl.DisplayAlerts = False wb = xl.Workbooks.Open(PA) wb.Sheets("synoptique-bilan µmodules").Select() # dans la sheet visée, détecter tout les objets OLE (qui seront # normalement tous des déssins visio) OLEObjects = wb.Sheets("synoptique-bilan µmodules").OLEObjects() # pour chaque déssin ... for OLEObject in OLEObjects: # l'ouvrir dans Visio OLEObject.Verb(2) # prendre la main sur la fenêtre visio ouverte Visio = GetActiveObject("Visio.Application") # Visio.Visible = False Visio.DisplayAlerts = False ActiveWindow = Visio.ActiveWindow Page = ActiveWindow.Page Shapes = Page.Shapes msg = "Voulez confirmer le nombre de PBs après chaque sélection?\n" \ + "(si c'est plan assez complexe mieux vaut répondre par oui)" yn = ynbox(msg) # allons-y! # On extrait d'abord les infos d'entête for shape in Shapes: text = shape.Text if text.startswith('NRO'): bloc_NRO = text elif text.startswith('PT'): try: blocs_PT.append(shape) except: blocs_PT = [shape] elif text.startswith('PA'): PA_posx = get_XY(shape)[0] if get_XY(blocs_PT[0])[0] > get_XY(blocs_PT[1])[0]: FI_bloc = blocs_PT[0] PA_bloc = blocs_PT[1] else: PA_bloc = blocs_PT[1] FI_bloc = blocs_PT[0] PA_PT = PA_bloc.Text.rsplit('\n')[0].replace('PT: ', '') PMZ_PT = FI_bloc.Text.rsplit('\n')[0].replace('PT: ', '') CH = PA_bloc.Text.rsplit('\n')[2].replace('CH: ', '') NRO = extract('NRO/PMZ/PA', bloc_NRO, 'NRO') ADRESSE1 = ' '.join(PA_bloc.Text.rsplit('\n')[3:5])\ .replace('Adresse: ', '') ADRESSE2 = ADRESSE1.rsplit('-')[0] TRs = {} empty_TRs = [] # là ça va barder! for shape in Shapes: if shape.Text.startswith('TR'): if get_XY(shape)[0] > PA_posx: TR_TXT = str(shape.Text.encode()).replace("b'", '').replace("'", '') TR = TR_TXT.rsplit('FO')[0] \ .replace('\\n', ' ') + 'FO' if not re.match(r'TR\s+\d{2}\s+\d{4}\s+\d+FO', TR): empty_TRs.append(shape.ID) continue if TR not in TRs: TRs[TR] = { 'LONG': 0, 'SHAPES': [shape.ID], 'CH/IMB/AP': [], 'PTs': [], 'maxPT': 0 } else: TRs[TR]['SHAPES'].append(shape.ID) try: TR_LONG = int(TR_TXT.rsplit('\\xe2\\x80\\x93 ')[1] \ .replace('m', '')) except: TR_LONG = 0 TRs[TR]['LONG'] = TRs[TR]['LONG'] + TR_LONG title1 = 'Sélectionnez les bloc' title2 = 'Confirmez la sélection' for TR in TRs: while True: SelectShapes(TRs[TR]['SHAPES']) if ccbox(TR, title1): CH_OR_IMB_OR_AP_all = [] PTs = [] msg = "Pour " + TR + "\nVous avez sélectionné:\n" selected_PBs = 0 yn_yes = True for selected in ActiveWindow.Selection: try: TEXT = str(selected.Text) if not TEXT.startswith('PB'): continue selected_PBs = selected_PBs + 1 PT = TEXT.rsplit('\n')[2] ADR = TEXT.rsplit('\n')[3] CH_OR_IMB_OR_AP = TEXT.rsplit('\n')[4] if (not CH_OR_IMB_OR_AP.startswith('AP ') and not CH_OR_IMB_OR_AP.startswith('Ch.') and not CH_OR_IMB_OR_AP.startswith('IMB')): SelectShapes([selected.ID]) msgbox("T'as surement encore fais une connerie dans tes" + "déssins, regarde ce bloc dans la ligne PT!\n" + "Je devrais trouver Ch.XXXX ou AP XXXX" + "ou IMB/XXXX/XXX mais j'ai trouvé\n" + CH_OR_IMB_OR_AP + "\n" + "Quand t'auras détécté l'erreur click sur OK") cont = boolbox("Dois-je continuer ou fermer?", "Que faire?", ['Continuer?', 'Fermer?']) if not cont: exit(0) else: pass else: msg = msg + "- " + CH_OR_IMB_OR_AP + "\n" CH_OR_IMB_OR_AP_all.append([ADR, CH_OR_IMB_OR_AP]) PTs.append(int(PT.replace('PT', ''))) except: SelectShapes([selected.ID]) msgbox("T'as surement encore fais une connerie dans tes" + "déssins, regarde ce bloc dans la ligne PT!\n" + "Quand t'auras détécté l'erreur click sur OK") cont = boolbox("Dois-je continuer ou fermer?", "Que faire?", ['Continuer?', 'Fermer?']) if not cont: exit(0) else: msg = msg + "(RIEN!)" CH_OR_IMB_OR_AP_all = [] PTs = [] yn_yes = False if not selected_PBs: cont = boolbox("Tu n'as rien sélectionné! Tu confirmes" + " que ce n'est pas une connerie?", "Sélection vide!", ['Oui vas-y', 'Comme d\'hab! Une connerie']) if cont: break else: continue if yn and yn_yes: msg = msg + "(" + str(selected_PBs) + " sélectionnés)" conf = boolbox(msg, title2, ['Confirmer?', 'Refaire?']) if conf: TRs[TR]['CH/IMB/AP'] = CH_OR_IMB_OR_AP_all TRs[TR]['PTs'] = PTs break else: pass else: TRs[TR]['CH/IMB/AP'] = CH_OR_IMB_OR_AP_all TRs[TR]['PTs'] = PTs break else: exit(0) if len(TRs[TR]['PTs']): TRs[TR]['maxPT'] = 'DE_PT%06d' % max(TRs[TR]['PTs']) + '.doc' else: TRs[TR]['maxPT'] = 'je_ne_suis_pas_cense_exister.doc' if TRs == {}: msgbox("il n'y pas de TR valide sur ce déssin") TRs_all.append(TRs) Visio.Visible = False RESULTS[PA] = { 'TRs_all': TRs_all, 'NRO': NRO, 'PMZ_PT': PMZ_PT, 'PA_PT': PA_PT, 'CH': CH, 'ADRESSE1': ADRESSE1, 'ADRESSE2': ADRESSE2, 'DATE': DATE } xl.Quit() return except: print(format_exc()) codebox("t'as encore fais une connerie! Fais moi un screen de malheur!", "Erreur", format_exc()) going()
def process(PA): global ActiveWindow, Shapes, Word, TRs_all, xl, Visio global RESULTS # Bien gérer les erreurs try: # ouvrir le fichier excel et faire les initialisations de coutume xl = CreateObject("Excel.application") xl.Visible = False xl.DisplayAlerts = False PA_wb = xl.Workbooks.Open(PA) PA_wb.Sheets("synoptique-bilan µmodules").Select() # dans la sheet visée, détecter tout les objets OLE (qui seront # normalement tous des déssins visio) OLEObjects = PA_wb.Sheets("synoptique-bilan µmodules").OLEObjects() # pour chaque déssin ... for OLEObject in OLEObjects: # l'ouvrir dans Visio OLEObject.Verb(2) # prendre la main sur la fenêtre visio ouverte Visio = GetActiveObject("Visio.Application") # Visio.Visible = False Visio.DisplayAlerts = False ActiveWindow = Visio.ActiveWindow Page = ActiveWindow.Page Shapes = Page.Shapes # Ceci est pour les déssins plutôt compliqués, après chaque sélection des PB, le script # les affichera et demandra de confirmer si c'est bon ou non msg = "Voulez confirmer le nombre de PBs après chaque sélection?\n" \ + "(si c'est plan assez complexe mieux vaut répondre par oui)" yn = ynbox(msg) # allons-y! # On extrait d'abord les infos d'entête for shape in Shapes: text = shape.Text if text.startswith('NRO'): bloc_NRO = text elif text.startswith('PT'): # certaines shapes buguent je ne sais pas pourquoi, elles n'ont pas d'utilité try: blocs_PT.append(shape) except: blocs_PT = [shape] elif text.startswith('PA'): bloc_PA = text # On extrait la position x du PA pour prendre toutes les TR qui sont à droite PA_posx = get_XY(shape)[0] # Les deux blocs FI et PA tout deux commencent par PT, celui de PA est plus à gauche # on les différenciera par leur position if get_XY(blocs_PT[0])[0] < get_XY(blocs_PT[1])[0]: FI_bloc = blocs_PT[0] PA_bloc = blocs_PT[1] else: FI_bloc = blocs_PT[1] PA_bloc = blocs_PT[0] PA_PT = PA_bloc.Text.rsplit('\n')[0].replace('PT: ', '') PMZ_PT = FI_bloc.Text.rsplit('\n')[0].replace('PT: ', '') CH = PA_bloc.Text.rsplit('\n')[2].replace('CH: ', '') NRO = extract('NRO/PMZ/PA', bloc_NRO, 'NRO') ADRESSE1 = ' '.join(PA_bloc.Text.rsplit('\n')[3:5])\ .replace('Adresse: ', '') ADRESSE2 = ADRESSE1.rsplit('-')[0] # Les TRs du déssin courant TRs = {} # là ça va barder! for shape in Shapes: if shape.Text.startswith('TR'): # Seulement ceux qui sont plus à droite de PA if get_XY(shape)[0] > PA_posx: # Le text est un peu bizarre, il est vraiment en texte mais paraît être un # bytes! On doit le nettoyer TR_TXT = str(shape.Text.encode()).replace("b'", '').replace("'", '') # Extraire ne TR TR = TR_TXT.rsplit('FO')[0] \ .replace('\\n', ' ') + 'FO' # Si ce n'est pas un TR valide, passer if not re.match(r'TR\s+\d{2}\s+\d{4}\s+\d+FO', TR): continue # Si ce TR n'a pas encore été enregistré dans la liste TRs, l'enregistrer ## Initialiser la longueur à 0 ## Mettre le shape courant dans la liste "shapes" ## Initialiser une liste vide pour les CH ou IMB ou AP qui vont avec ## Initialiser une liste vide pour les PTs qui vont avec (pour le nommage) ## Et initialiser une variable "0" pour le PT qui est maximum (pour le nommage) if TR not in TRs: TRs[TR] = { 'LONG': 0, 'SHAPES': [shape.ID], 'CH/IMB/AP': [], 'PTs': [], 'maxPT': 0 } # Sinon si le TR est déjà dans TRs, ajouter le shape courant à "SHAPES" else: TRs[TR]['SHAPES'].append(shape.ID) # Essayer d'extraire la longueur du TR courant try: TR_LONG = int(TR_TXT.rsplit('\\xe2\\x80\\x93 ')[1] \ .replace('m', '')) except: TR_LONG = 0 # Et incrémenter la longueur du TR global corréspondant à cette ligne TRs[TR]['LONG'] = TRs[TR]['LONG'] + TR_LONG # Message pour que l'utilisateur sélectionner les blocs PB pour chaque TR title1 = 'Sélectionnez les bloc' title2 = 'Confirmez la sélection' # Pour chaque TR dans TRs for TR in TRs: # Python n'a pas de "REDO", on hack avec un "WHILE" while True: # Sélectionner toutes les shapes de cette ligne de TR SelectShapes(TRs[TR]['SHAPES']) # Demander lui de sélectionner, quand il confirme continuer... if ccbox(TR, title1): # Une liste vide pour tout les PB dans ce TR CH_OR_IMB_OR_AP_all = [] # Une liste vide pour tout les PTs dans ce TR PTs = [] # Une liste vide pour tout les PBs dans ce TR PBs = [] # Un message au cas où l'utilisateur aurait choisit une confirmation msg = "Pour " + TR + "\nVous avez sélectionné:\n" # Le nombre de PBs sélectionnées (pour affichage dans la confirmation) selected_PBs = 0 # Au cas où il n'y aurait pas de PB valide, pas la peine de mettre une # fenêtre de confirmation, supposer tout de même qu'il y'en a ... yn_yes = True # Pour chaque fenêtre sélectionnée for selected in ActiveWindow.Selection: # (certains shapes n'aiment pas qu'on appelle leur .Text!!!!) try: TEXT = str(selected.Text) # Prendre seulement les blocs qui commencent par "PB" if not TEXT.startswith('PB'): continue # Incrémenter le nombre de PBs trouvés par +1 selected_PBs = selected_PBs + 1 # Enregister le PB, PT, l'adresse, et le text qui peut être un: ## Ch.XXXXX ## IMB/XXXXX/XXXX ## AP XXXX PB = TEXT.rsplit('\n')[0].rstrip() PT = TEXT.rsplit('\n')[2] ADR = TEXT.rsplit('\n')[3] CH_OR_IMB_OR_AP = TEXT.rsplit('\n')[4] # Si l'un de ces lignes ne se trouve pas à la bonne place if (not CH_OR_IMB_OR_AP.startswith('AP ') and not CH_OR_IMB_OR_AP.startswith('Ch.') and not CH_OR_IMB_OR_AP.startswith('IMB')): # Resélectionner les sélectionnés (pfff sert à rien ça!) SelectShapes([selected.ID]) # Et dire qu'il y a un truc qui cloche! msgbox("T'as surement encore fais une connerie dans tes" + "déssins, regarde ce bloc dans la ligne PT!\n" + "Je devrais trouver Ch.XXXX ou AP XXXX" + "ou IMB/XXXX/XXX mais j'ai trouvé\n" + CH_OR_IMB_OR_AP + "\n" + "Quand t'auras détécté l'erreur click sur OK") # Continuer ou quitter! cont = boolbox("Dois-je continuer ou fermer?", "Que faire?", ['Continuer?', 'Fermer?']) if not cont: exit(0) else: pass else: # Sinon, préparer le message de confirmation msg = msg + "- " + CH_OR_IMB_OR_AP + "\n" # Et ajouter le CH/IMB/AP à la liste CH_OR_IMB_OR_AP_all.append([ADR, CH_OR_IMB_OR_AP]) # Ajouter le PT de ce bloc à la liste PTs PTs.append(int(PT.replace('PT', ''))) # Ajouter le PB de ce bloc à la liste PBs PBs.append(PB) except: # Si quelque chose cloche, trouver une porte de sortie!!: SelectShapes([selected.ID]) msgbox("T'as surement encore fais une connerie dans tes" + "déssins, regarde ce bloc dans la ligne PT!\n" + "Quand t'auras détécté l'erreur click sur OK") cont = boolbox("Dois-je continuer ou fermer?", "Que faire?", ['Continuer?', 'Fermer?']) # Vraiment je ne sais pas à quoi sert ce que j'ai écrit dans les # 8 prochaines lignes!!!! if not cont: exit(0) else: msg = msg + "(RIEN!)" CH_OR_IMB_OR_AP_all = [] PTs = [] PBs = [] yn_yes = False # S'il n'a rien sélectionné if not selected_PBs: cont = boolbox("Tu n'as rien sélectionné! Tu confirmes" + " que ce n'est pas une connerie?", "Sélection vide!", ['Oui vas-y', 'Comme d\'hab! Une connerie']) # Soit on quitte! if cont: break # Soit c'est délibéré et on continue else: continue # Si l'utilisateur avait demandé une confirmation, la montrer # (S'il y a eu une erreur, yn_yes est False, et pas la peine de montrer la # confirmation) if yn and yn_yes: msg = msg + "(" + str(selected_PBs) + " sélectionnés)" conf = boolbox(msg, title2, ['Confirmer?', 'Refaire?']) if conf: # Si c'est confirmé, stocher ces données pour le shape TRs[TR]['CH/IMB/AP'] = CH_OR_IMB_OR_AP_all TRs[TR]['PTs'] = PTs TRs[TR]['PBs'] = PBs break else: pass # Sinon s'il n'avait pas demandé de confirmation, stocker ces données # directement pour le shape else: TRs[TR]['CH/IMB/AP'] = CH_OR_IMB_OR_AP_all TRs[TR]['PTs'] = PTs TRs[TR]['PBs'] = PBs break # En cas d'erreur sortir :-( else: exit(0) # Il doit y avoir au moins un PT pour créer un fichier doc et xls avec le max des TRs if len(TRs[TR]['PTs']): TRs[TR]['DE_filename'] = 'DE_PT%06d' % max(TRs[TR]['PTs']) + '.doc' TRs[TR]['AR_filename'] = 'AR_PT%06d' % max(TRs[TR]['PTs']) + '.xls' # Les fichiers avec ce nom ne devront jamais voir le jour! else: TRs[TR]['DE_filename'] = 'je_ne_suis_pas_cense_exister.doc' TRs[TR]['AR_filename'] = 'je_ne_suis_pas_cense_exister.xls' # Un cas très particulier m'a forcé à ajourer la ligne suivant! TRs[TR]['PBs'] = [] # Si je n'ai trouvé aucun TR, montrer un message if TRs == {}: msgbox("il n'y pas de TR valide sur ce déssin") # Ajouter ces TRs à TR_all TRs_all.append(TRs) # Cacher le déssin Visio Visio.Visible = False # Demander qui est le client xl.Visible = True msg = "Quel est le client pour cette fiche PA?" choices = ["Circet","Engie"] client = buttonbox(msg, choices=choices) # Résultat globaux pour cette fiche PA RESULTS[PA] = { 'PA_REF': bloc_PA, 'client': client, 'TRs_all': TRs_all, 'NRO': NRO, 'PMZ_PT': PMZ_PT, 'PA_PT': PA_PT, 'CH': CH, 'ADRESSE1': ADRESSE1, 'ADRESSE2': ADRESSE2, 'DATE': DATE } # Quitter excel et passer à la prochaine fiche PA xl.Quit() return except: # En cas d'erreur innatendue! print(format_exc()) codebox("t'as encore fais une connerie! Fais moi un screen de malheur!", "Erreur", format_exc()) going()