libreoffice-python-script/BookmarkExec.py
2025-03-24 11:49:58 +08:00

428 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
)