You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LibreOffice宏生成树形CSV自定义ID:子节点ID生成失败修正

问题:树形结构CSV生成规则ID的宏代码修正

我有一个树形结构的CSV文件,行数据通过Id(A列)与ParentId(B列)字段对应父子节点关系。需要在H列生成符合规则的ID:

  • 含“RecordGrp”(E列)的行生成以“2022-54-”开头的递增ID
  • 其子节点也按顺序生成连续递增的ID

当前使用的宏代码无法为子节点正确生成ID,期望的输出示例如下(H列为生成的目标ID):

ID290,ID11,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300254\T30_1300254_69402_accuse reception courrier.pdf,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300254\T30_1300254_69402_accuse reception courrier.pdf,Item,T30_1300254_69402_accuse reception courrier.pdf,,2022-54-2
ID293,ID11,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300254\T30_1300254_69417_accuse reception courrier.pdf,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300254\T30_1300254_69417_accuse reception courrier.pdf,Item,T30_1300254_69417_accuse reception courrier.pdf,,2022-54-3
ID11,ID10,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300254,,RecordGrp,Dossier n° 1300254,,2022-54-1
ID333,ID294,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300826\T30_1300826_53417_accuse reception courrier.pdf,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300826\T30_1300826_53417_accuse reception courrier.pdf,Item,T30_1300826_53417_accuse reception courrier.pdf,,2022-54-5
ID336,ID294,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300826\T30_1300826_59180_accuse mise a disposition courrier.pdf,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300826\T30_1300826_59180_accuse mise a disposition courrier.pdf,Item,T30_1300826_59180_accuse mise a disposition courrier.pdf,,2022-54-6
ID339,ID294,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300826\T30_1300826_59390_accuse reception courrier.pdf,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300826\T30_1300826_59390_accuse reception courrier.pdf,Item,T30_1300826_59390_accuse reception courrier.pdf,,2022-54-7
ID294,ID10,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300826,,RecordGrp,Dossier n° 1300826,,2022-54-4
ID400,ID340,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300897\T30_1300897_69841_accuse mise a disposition courrier.pdf,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300897\T30_1300897_69841_accuse mise a disposition courrier.pdf,Item,T30_1300897_69841_accuse mise a disposition courrier.pdf,,2022-54-9
ID403,ID340,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300897\T30_1300897_69858_accuse reception courrier.pdf,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300897\T30_1300897_69858_accuse reception courrier.pdf,Item,T30_1300897_69858_accuse reception courrier.pdf,,2022-54-10
ID340,ID10,..\Phase2-fusionner_dossiers\Dossiers\TA30\Dossier n° 1300897,,RecordGrp,Dossier n° 1300897,,2022-54-8

原宏代码

Dim oSheet As Object
Dim oCursor As Object
Dim lastRow As Long
Dim currentId As String
Dim counter As Long
Dim parentMap As Object
Dim row As Long

' Initialiser la feuille active et les variables
oSheet = ThisComponent.CurrentController.ActiveSheet
oCursor = oSheet.createCursor()
oCursor.gotoEndOfUsedArea(True)
lastRow = oCursor.RangeAddress.EndRow
Set parentMap = CreateObject("Scripting.Dictionary")
counter = 1
currentId = "2022-54-"

' Parcourir les lignes
For row = 1 To lastRow
    Dim title As String
    Dim descriptionLevel As String
    Dim parentId As String
    Dim id As String
    Dim newId As String
    
    title = oSheet.getCellByPosition(5, row).String  ' Colonne F : Content.Title
    descriptionLevel = oSheet.getCellByPosition(4, row).String  ' Colonne E : Content.DescriptionLevel
    id = oSheet.getCellByPosition(0, row).String  ' Colonne A : Id
    parentId = oSheet.getCellByPosition(1, row).String  ' Colonne B : ParentId

    If descriptionLevel = "RecordGrp" Then
        ' Nouvel identifiant pour les "RecordGrp"
        newId = currentId & counter
        parentMap.Add id, newId
        oSheet.getCellByPosition(7, row).String = newId  ' Colonne H pour l'ID
        counter = counter + 1
    ElseIf parentMap.exists(parentId) Then
        ' Utiliser l'identifiant du parent pour les enfants
        newId = currentId & counter
        oSheet.getCellByPosition(7, row).String = newId  ' Colonne H pour l'ID
        counter = counter + 1
    Else
        ' Si aucun parent trouvé, signaler une erreur
        oSheet.getCellByPosition(7, row).String = "Erreur : Parent introuvable"
    End If
Next row

MsgBox "Identifiants générés avec succès dans la colonne H !"
End Sub

问题分析

原代码的核心问题是遍历顺序错误:当前按行号顺序遍历,但示例中RecordGrp父节点(如ID11)在其子节点之后,导致处理子节点时父节点的ID还未存入parentMap,触发错误。此外,原代码仅存储RecordGrp节点的映射,未覆盖所有节点,无法处理多层级树形结构的情况。

修正后的宏代码

Dim oSheet As Object
Dim oCursor As Object
Dim lastRow As Long
Dim currentIdPrefix As String
Dim globalCounter As Long
Dim nodeMap As Object
Dim row As Long

' 初始化工作表和变量
oSheet = ThisComponent.CurrentController.ActiveSheet
oCursor = oSheet.createCursor()
oCursor.gotoEndOfUsedArea(True)
lastRow = oCursor.RangeAddress.EndRow
Set nodeMap = CreateObject("Scripting.Dictionary") ' 存储所有节点的原始ID到新ID的映射
globalCounter = 1
currentIdPrefix = "2022-54-"

' 第一步:先遍历所有行,将所有节点ID存入映射(占位符后续填充)
For row = 1 To lastRow
    Dim id As String
    id = oSheet.getCellByPosition(0, row).String ' 读取A列的原始ID
    If Not nodeMap.exists(id) Then
        nodeMap.Add id, "" ' 初始化空值,后续填充新ID
    End If
Next row

' 第二步:遍历所有行,优先处理RecordGrp节点,再处理子节点
For row = 1 To lastRow
    Dim descriptionLevel As String
    Dim parentId As String
    Dim newId As String
    
    descriptionLevel = oSheet.getCellByPosition(4, row).String ' E列:Content.DescriptionLevel
    id = oSheet.getCellByPosition(0, row).String ' A列:Id
    parentId = oSheet.getCellByPosition(1, row).String ' B列:ParentId

    If descriptionLevel = "RecordGrp" Then
        ' 为RecordGrp生成新ID
        newId = currentIdPrefix & globalCounter
        nodeMap(id) = newId
        oSheet.getCellByPosition(7, row).String = newId ' 写入H列
        globalCounter = globalCounter + 1
    Else
        ' 处理子节点:检查父节点是否已有映射
        If nodeMap.exists(parentId) And nodeMap(parentId) <> "" Then
            newId = currentIdPrefix & globalCounter
            nodeMap(id) = newId
            oSheet.getCellByPosition(7, row).String = newId ' 写入H列
            globalCounter = globalCounter + 1
        Else
            ' 父节点未处理或不存在,标记错误
            oSheet.getCellByPosition(7, row).String = "Erreur : Parent introuvable"
        End If
    End If
Next row

MsgBox "Identifiants générés avec succès dans la colonne H !"
End Sub

修正说明

  1. 两次遍历逻辑:第一次遍历先将所有节点ID存入nodeMap,确保无论行顺序如何,父节点都能被追踪;第二次遍历优先处理RecordGrp节点生成初始ID,再按顺序处理子节点。
  2. 全局计数器:使用全局递增计数器,保证所有ID(包括RecordGrp和子节点)按顺序连续生成,符合示例要求。
  3. 完善映射覆盖:nodeMap存储所有节点的ID映射,支持多层级树形结构的子节点处理。

内容的提问来源于stack exchange,提问作者Pick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:47:01