2
votes

openpyxl en Python la fonction delete_rows rompt la cellule fusionnée

J'utilise openpyxl 2.6.0 en Python3 (avec Django).

Je veux manipuler ma feuille Excel Skelton (certaines cellules sont fusionnées) pour supprimer une ligne. Mais après la suppression de la ligne, les cellules fusionnées ne sont plus fusionnées.

Je souhaite conserver les cellules fusionnées même si certaines lignes sont supprimées.

Le code et l'exemple Excel se trouvent ci-dessous.

def excelsample(request):

    wb = openpyxl.load_workbook(os.path.join(settings.BASE_DIR, 'static', 'excel', 'sample.xlsx'))

    sheet = wb['Sheet1']
    sheet.delete_rows(6) # delete 6th row

    response = HttpResponse(content_type='application/vnd.ms-excel')
    response['Content-Disposition'] = 'attachment; filename="{fn}"'.format(fn=urllib.parse.quote("excelsample.xlsx"))

    wb.save(response)

    return response

Avant:

 entrez la description de l'image ici

Après:

 entrez la description de l'image ici


0 commentaires

3 Réponses :



1
votes

Pour openpyxl 3.04 et Python 3.8.5, le code de la réponse de Stephen Rauch ne fonctionne que si nous changeons en dans la clause elif:

def delete_row_with_merged_ranges(sheet, idx):
    sheet.delete_rows(idx)
    for mcr in sheet.merged_cells:
        if idx < mcr.min_row:
            mcr.shift(row_shift=-1)
        elif idx < mcr.max_row:
            mcr.shrink(bottom=1)


3 commentaires

Je ne sais pas pourquoi vous avez copié la solution à partir de la réponse publiée précédemment. Il suffirait de commenter cette réponse pour dire: "Cette solution fonctionne avec openpyxl 3.04 python 3.8.5"


ce n'est pas seulement une copie, c'est une ligne de contrôle de correction # 6, il devrait être


Je pense toujours qu'il aurait été préférable d'ajouter un commentaire à la réponse originale. Mais merci pour la contribution. J'ai changé votre réponse pour souligner la différence. Comme il sera approuvé, vous le verrez. S'il s'avère que votre version fonctionne bien avec toutes les versions de Python / openpyxl ou pour différentes versions, nous avons besoin de solutions différentes, nous devons corriger cette réponse. Il sera plus facile de trouver la réponse.



0
votes

Je ne peux pas ajouter de commentaire à la réponse de Stephen Rauch, car je n'ai pas assez de réputation pour commenter.

Si vous souhaitez supprimer de nombreuses lignes, le code est ici:

    def delete_rows(self, idx: int, amount: int = 1):
        self.sheet.delete_rows(idx, amount)
        merged_cells = [_ for _ in self.sheet.merged_cells.ranges]
        for index, mcr in enumerate(merged_cells):
            if idx < mcr.min_row:
                if idx + amount - 1 >= mcr.min_row:
                    mcr.shrink(top=idx + amount - mcr.min_row)
                    if mcr.min_row > mcr.max_row:
                        self.sheet.merged_cells.ranges.remove(mcr)
                        continue
                mcr.shift(row_shift=-amount)
            elif idx <= mcr.max_row:
                mcr.shrink(bottom=min(mcr.max_row - idx + 1, amount))
            if mcr.min_row > mcr.max_row:
                self.sheet.merged_cells.ranges.remove(mcr)


0 commentaires