import json import time def ReplaceOne(bookmark_obj_collection, bookmark_name, new_value): """ 替换一个书签 Args: bookmark_obj_collection: 书签对象集合 bookmark_name: 书签名称 new_value: 新值 """ if bookmark_obj_collection.hasByName(bookmark_name): bookmark = bookmark_obj_collection.getByName(bookmark_name) anchor = bookmark.getAnchor() anchor.setString(new_value) def ReplaceAll(bookmark_obj_collection, bookmark_name_value_map): """ 替换所有书签 Args: bookmark_obj_collection: 书签对象集合 bookmark_name_value_map: 书签名称和新值的映射 """ for bookmark_name, new_value in bookmark_name_value_map.items(): ReplaceOne(bookmark_obj_collection, bookmark_name, new_value) def Replace(bookmark_name_value_map): """ 替换所有书签 Args: bookmark_name_value_map: 书签名称和新值的映射 """ doc = XSCRIPTCONTEXT.getDocument() bookmarks = doc.getBookmarks() ReplaceAll(bookmarks, bookmark_name_value_map) def ReplaceWithJSON(json_str): """ 替换所有书签 Args: json_str: 书签名称和新值的映射的JSON字符串 """ bookmark_name_value_map = json.loads(json_str) Replace(bookmark_name_value_map) def DebugCallReplace(): """ 调试调用 """ Replace({"h1": "P1", "h2": "P2", "h3": "P3"}) def DebugCallReplaceList(): """ 调试调用,替换list """ Replace({"list": "1\r2\r3\r4"}) def QueryAll(inner_call=False): """ 查询所有书签,表格中的书签获取对应表格index 返回结果格式: { "text": [], "table": [ { "tableIndex": 表格索引, "bookmark": [书签名称列表] } ] } """ doc = XSCRIPTCONTEXT.getDocument() bookmarks = doc.getBookmarks() bookmark_names = bookmarks.getElementNames() result = {"text": [], "table": []} tables = doc.getTextTables() bookmark_in_table_position = QueryBookmarkPositionInTable(tables, bookmarks) existing_table_indices = {} for bk_name in bookmark_names: if bk_name in bookmark_in_table_position: table_index = bookmark_in_table_position[bk_name]["tableIndex"] if table_index in existing_table_indices: index = existing_table_indices[table_index] result["table"][index]["bookmark"].append(bk_name) else: new_entry = {"tableIndex": table_index, "bookmark": [bk_name]} result["table"].append(new_entry) existing_table_indices[table_index] = ( len(result["table"]) - 1 ) # 更新索引记录 else: result["text"].append(bk_name) return result def QueryBookmarkPositionInTable(tables, bookmarks): """ 查询书签在表格中的位置 {'bk1': {'tableIndex': 0, 'row': 0, 'col': 0}, 'bk2': {'tableIndex': 0, 'row': 0, 'col': 2}} """ bookmark_names = bookmarks.getElementNames() bookmark_position = {} for table_index in range(tables.getCount()): table = tables.getByIndex(table_index) col_count = table.getColumns().getCount() row_count = table.getRows().getCount() for row in range(row_count): for col in range(col_count): cell = table.getCellByPosition(col, row) cell_text_obj = cell.getText() for bk_name in bookmark_names: bookmark_obj = bookmarks.getByName(bk_name) bookmark_text_obj = bookmark_obj.getAnchor().getText() if cell_text_obj == bookmark_text_obj: bookmark_position[bk_name] = { "tableIndex": table_index, "col": col, "row": row, } print(bookmark_position) return bookmark_position def CreateRow(table, row_count): """ 创建表格行 """ table.getRows().insertByIndex(table.getRows().getCount(), row_count) def FindTableIndex(table_bookmarks, location_bookmark_name): """ 找到表格索引 """ handle_table_index = -1 for table_info in table_bookmarks: if location_bookmark_name in table_info["bookmark"]: handle_table_index = table_info["tableIndex"] break if handle_table_index == -1: raise ValueError(f"未找到书签 {location_bookmark_name} 对应的表格") return handle_table_index def InsertRow(location_bookmark_name, data, start_row_index=-1): """ 表格插入行 Args: location_bookmark_name: 用于定位表格的书签 data: 二维数组,用于填充表格数据 start_row_index: 起始行位置,默认为-1,即在表格末尾插入 """ bookmark_info = QueryAll(inner_call=True) table_bookmarks = bookmark_info["table"] handle_table_index = FindTableIndex(table_bookmarks, location_bookmark_name) doc = XSCRIPTCONTEXT.getDocument() tables = doc.getTextTables() try: handle_table = tables.getByIndex(handle_table_index) except IndexError: raise IndexError(f"表格索引 {handle_table_index} 超出范围") col_count = handle_table.getColumns().getCount() row_count = handle_table.getRows().getCount() if not data or len(data) == 0: return if any(len(row) != col_count for row in data): raise ValueError(f"数据列数不匹配,表格有 {col_count} 列") try: for _ in range(len(data)): if start_row_index > 0 & start_row_index < row_count: handle_table.getRows().insertByIndex(start_row_index, 1) else: handle_table.getRows().insertByIndex(row_count, 1) for row_idx, row_data in enumerate(data, start=row_count): for col_idx, cell_value in enumerate(row_data): cell = handle_table.getCellByPosition(col_idx, row_idx) cell.setString(str(cell_value)) except Exception as e: raise RuntimeError(f"插入行时发生错误: {str(e)}") def DebugCallInsertRow(): """ 调试调用 """ InsertRow("h1", [["1", "2", "3"], ["4", "5", "6"]], 0) def DeleteRow(location_bookmark_name, start_row_index, delete_row_count): """ 删除表格行 Args: location_bookmark_name: 用于定位表格的书签 start_row_index: 起始行位置(删除行包含本行) delete_row_count: 删除的行数 """ bookmark_info = QueryAll() table_bookmarks = bookmark_info["table"] handle_table_index = FindTableIndex(table_bookmarks, location_bookmark_name) doc = XSCRIPTCONTEXT.getDocument() tables = doc.getTextTables() handle_table = tables.getByIndex(handle_table_index) row_count = handle_table.getRows().getCount() if start_row_index < 0 or start_row_index >= row_count: raise ValueError(f"起始行索引 {start_row_index} 超出范围") if start_row_index + delete_row_count > row_count: raise ValueError(f"删除行数量 {delete_row_count} 超出范围") try: handle_table.getRows().removeByIndex(start_row_index, delete_row_count) except Exception as e: raise RuntimeError(f"删除行时发生错误: {str(e)}") def DebugCallDeleteRow(): """ 调试调用 """ DeleteRow("h1", 1, 2) def LocateBookmark(bookmark_name): """ 定位书签并选中内容 Args: bookmark_name: 要定位的书签名称 """ doc = XSCRIPTCONTEXT.getDocument() if False == doc.getBookmarks().hasByName(bookmark_name): return bookmark = doc.getBookmarks().getByName(bookmark_name) try: # 获取书签的文本范围锚点 anchor = bookmark.getAnchor() # 获取文档控制器 controller = doc.getCurrentController() # 将视图光标移动到书签位置并选中 view_cursor = controller.getViewCursor() view_cursor.gotoRange(anchor, False) # False表示不扩展选区 # 如果需要高亮显示(可选) controller.select(anchor) # 确保窗口可见(针对隐藏窗口的情况) try: window = controller.getFrame().getContainerWindow() window.setVisible(True) window.toFront() except Exception: pass except Exception as e: raise RuntimeError(f"定位书签失败: {str(e)}") from e def DebugCallLocateBookmarkLo1(): LocateBookmark("lo1") def DebugCallLocateBookmarkLo2(): LocateBookmark("lo2") def InsertBookmark(bookmark_name): """ 选中内容插入书签,如果没有选中任何内容,插入点书签 Args: bookmark_name: 要插入的书签名称 """ doc = XSCRIPTCONTEXT.getDocument() controller = doc.getCurrentController() # 获取当前选区 selection = controller.getSelection() # 检查是否已存在同名书签,如果存在则先删除 bookmarks = doc.getBookmarks() if bookmarks.hasByName(bookmark_name): bookmarks.removeByName(bookmark_name) try: # 创建书签 if selection.getCount() > 0: # 尝试获取选区的第一个元素 range_to_bookmark = selection.getByIndex(0) # 创建书签并附加到选区 bookmark = doc.createInstance("com.sun.star.text.Bookmark") bookmark.attach(range_to_bookmark) bookmark.setName(bookmark_name) else: # 没有选中内容,创建点书签 cursor = controller.getViewCursor() text_cursor = cursor.getText().createTextCursorByRange(cursor) # 创建书签并附加到光标位置 bookmark = doc.createInstance("com.sun.star.text.Bookmark") bookmark.attach(text_cursor) bookmark.setName(bookmark_name) except Exception as e: raise RuntimeError(f"插入书签失败: {str(e)}") from e def DebugCallInsertBookmark(): """ 调试调用 """ InsertBookmark("bookmark_" + str(time.time())) def UpdateBookmark(bookmark_name, new_value): """ 修改书签名称(通过删除旧书签 + 插入新书签实现) Args: bookmark_name: 原书签名称 new_value: 新书签名称 """ doc = XSCRIPTCONTEXT.getDocument() bookmarks = doc.getBookmarks() if not bookmarks.hasByName(bookmark_name): raise ValueError(f"书签 '{bookmark_name}' 不存在") if bookmarks.hasByName(new_value): raise ValueError(f"书签 '{new_value}' 已存在") # 获取旧书签的锚点位置 old_bookmark = bookmarks.getByName(bookmark_name) old_bookmark.setName(new_value) def DebugCallUpdateBookmark(): """ 调试调用 """ UpdateBookmark("ole_bookmark", "new_bookmark") def DeleteBookmark(bookmark_name): """ 删除书签但保留内容(通过断开书签与锚点的关联) """ doc = XSCRIPTCONTEXT.getDocument() bookmarks = doc.getBookmarks() if not bookmarks.hasByName(bookmark_name): return bookmark = bookmarks.getByName(bookmark_name) if hasattr(bookmark, "Anchor"): try: anchor = bookmark.Anchor anchor.getText().removeTextContent(bookmark) except Exception as e: pass def DebugCallDeleteBookmark(): """ 调试调用 """ DeleteBookmark("remove_me") def CreateTable(location_bookmark_name, data): """ 创建表格 Args: location_bookmark_name: 用于定位表格的书签 data: 二维数组,用于填充表格数据 """ g_exportedScripts = ( Replace, ReplaceWithJSON, QueryAll, InsertRow, DeleteRow, DebugCallReplace, DebugCallReplaceList, DebugCallInsertRow, DebugCallDeleteRow, DebugCallLocateBookmarkLo1, DebugCallLocateBookmarkLo2, DebugCallInsertBookmark, DebugCallUpdateBookmark, DebugCallDeleteBookmark )