feat: replace bookmark with image
This commit is contained in:
parent
88db5957d2
commit
de95153976
169
BookmarkOP.py
169
BookmarkOP.py
@ -1,17 +1,12 @@
|
|||||||
import json
|
import json
|
||||||
import uno
|
|
||||||
import base64
|
import base64
|
||||||
import io
|
import io
|
||||||
from com.sun.star.text import XTextContent
|
|
||||||
from com.sun.star.text import XTextRange
|
|
||||||
from com.sun.star.text import XTextDocument
|
|
||||||
from com.sun.star.text import XTextCursor
|
|
||||||
from com.sun.star.text import XText
|
|
||||||
from com.sun.star.text import XBookmarksSupplier
|
|
||||||
from com.sun.star.text import XTextGraphicObjectsSupplier
|
|
||||||
from com.sun.star.graphic import XGraphicProvider
|
|
||||||
from com.sun.star.graphic import XGraphic
|
|
||||||
from com.sun.star.beans import PropertyValue
|
from com.sun.star.beans import PropertyValue
|
||||||
|
import tempfile
|
||||||
|
import os
|
||||||
|
from com.sun.star.beans import PropertyValue
|
||||||
|
from uno import ByteSequence, systemPathToFileUrl
|
||||||
|
from com.sun.star.text.TextContentAnchorType import AS_CHARACTER, AT_PARAGRAPH
|
||||||
|
|
||||||
def Replace(bookmark_name_value_map):
|
def Replace(bookmark_name_value_map):
|
||||||
"""
|
"""
|
||||||
@ -317,8 +312,8 @@ def BatchInsertRow(data_array):
|
|||||||
if not data or len(data) == 0:
|
if not data or len(data) == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
if any(len(row) != col_count for row in data):
|
# if any(len(row) != col_count for row in data):
|
||||||
raise ValueError(f"数据列数不匹配,表格有 {col_count} 列")
|
# raise ValueError(f"数据列数不匹配,表格有 {col_count} 列")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
row_count = handle_table.getRows().getCount()
|
row_count = handle_table.getRows().getCount()
|
||||||
@ -528,14 +523,15 @@ def ReplaceTextAndInsertTableRow(json_str):
|
|||||||
data = json.loads(json_str)
|
data = json.loads(json_str)
|
||||||
Replace(data["text"])
|
Replace(data["text"])
|
||||||
BatchInsertRow(data["table"])
|
BatchInsertRow(data["table"])
|
||||||
|
ReplaceBookmarkWithImage(data["image"])
|
||||||
|
|
||||||
|
|
||||||
def ReplaceTextAndInsertTableRowWithContentControl(json_str):
|
def ReplaceTextAndInsertTableRowWithContentControl(json_str):
|
||||||
data = json.loads(json_str)
|
data = json.loads(json_str)
|
||||||
SetDocumentToFormMode()
|
|
||||||
Replace(data["text"])
|
Replace(data["text"])
|
||||||
|
ReplaceBookmarkWithImage(data["image"])
|
||||||
BatchInsertRowWithContentControl(data["table"])
|
BatchInsertRowWithContentControl(data["table"])
|
||||||
ReplaceBookmarksWithControls({})
|
ReplaceBookmarksWithControls({}, ExtractBookmarkNames(data))
|
||||||
|
|
||||||
|
|
||||||
def returnWithJSON(data):
|
def returnWithJSON(data):
|
||||||
@ -559,32 +555,7 @@ def SaveDocument():
|
|||||||
print("err:", e)
|
print("err:", e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def SetDocumentToFormMode():
|
def ReplaceBookmarksWithControls(bookmark_name_value_map={}, exclude_bookmark_names=[]):
|
||||||
"""
|
|
||||||
将文档设置为限制编辑模式,启用强制保护,仅允许填写窗体
|
|
||||||
"""
|
|
||||||
doc = XSCRIPTCONTEXT.getDocument()
|
|
||||||
|
|
||||||
# 获取文档的控制器
|
|
||||||
controller = doc.getCurrentController()
|
|
||||||
|
|
||||||
# 获取文档的保护设置
|
|
||||||
protectable = doc.Protectable
|
|
||||||
|
|
||||||
# 启用强制保护
|
|
||||||
if not protectable.isProtected():
|
|
||||||
protectable.protect("") # 空字符串表示无密码保护
|
|
||||||
|
|
||||||
# 设置编辑限制为仅允许填写窗体
|
|
||||||
text_doc = doc.TextDocument
|
|
||||||
text_doc.setPropertyValue("EnableFormEdit", True)
|
|
||||||
text_doc.setPropertyValue("EnableFormFieldsOnly", True)
|
|
||||||
|
|
||||||
# 刷新视图
|
|
||||||
controller.refresh()
|
|
||||||
|
|
||||||
|
|
||||||
def ReplaceBookmarksWithControls(bookmark_name_value_map={}):
|
|
||||||
# 获取文档对象
|
# 获取文档对象
|
||||||
doc = XSCRIPTCONTEXT.getDocument()
|
doc = XSCRIPTCONTEXT.getDocument()
|
||||||
bookmarks = doc.getBookmarks()
|
bookmarks = doc.getBookmarks()
|
||||||
@ -595,6 +566,9 @@ def ReplaceBookmarksWithControls(bookmark_name_value_map={}):
|
|||||||
# 遍历所有需要处理的书签
|
# 遍历所有需要处理的书签
|
||||||
for name in bookmark_names:
|
for name in bookmark_names:
|
||||||
try:
|
try:
|
||||||
|
# 检查是否需要排除
|
||||||
|
if name in exclude_bookmark_names:
|
||||||
|
continue
|
||||||
# 检查书签是否存在
|
# 检查书签是否存在
|
||||||
if not bookmarks.hasByName(name):
|
if not bookmarks.hasByName(name):
|
||||||
continue
|
continue
|
||||||
@ -695,19 +669,20 @@ def NextEditableZone(current_index):
|
|||||||
raise RuntimeError(f"err: {str(e)}") from e
|
raise RuntimeError(f"err: {str(e)}") from e
|
||||||
|
|
||||||
def ReplaceBookmarkWithImage(data_array):
|
def ReplaceBookmarkWithImage(data_array):
|
||||||
""" 替换书签为图片 """
|
"""
|
||||||
# 获取当前文档
|
替换书签为图片,同时保留书签
|
||||||
|
参数:
|
||||||
|
data_array: 包含书签和图片信息的字典数组
|
||||||
|
"""
|
||||||
|
# 获取当前文档和相关服务
|
||||||
doc = XSCRIPTCONTEXT.getDocument()
|
doc = XSCRIPTCONTEXT.getDocument()
|
||||||
|
|
||||||
# 获取书签供应商
|
|
||||||
bookmarks = doc.getBookmarks()
|
bookmarks = doc.getBookmarks()
|
||||||
|
|
||||||
# 获取服务管理器
|
|
||||||
smgr = XSCRIPTCONTEXT.getComponentContext().getServiceManager()
|
smgr = XSCRIPTCONTEXT.getComponentContext().getServiceManager()
|
||||||
|
|
||||||
# 创建图形提供者服务
|
|
||||||
graphic_provider = smgr.createInstanceWithContext("com.sun.star.graphic.GraphicProvider", XSCRIPTCONTEXT.getComponentContext())
|
graphic_provider = smgr.createInstanceWithContext("com.sun.star.graphic.GraphicProvider", XSCRIPTCONTEXT.getComponentContext())
|
||||||
|
|
||||||
|
if not graphic_provider:
|
||||||
|
raise RuntimeError("无法初始化 GraphicProvider 服务")
|
||||||
|
|
||||||
for data in data_array:
|
for data in data_array:
|
||||||
bookmark_name = data["bookmarkName"]
|
bookmark_name = data["bookmarkName"]
|
||||||
image_data = data["imageData"]
|
image_data = data["imageData"]
|
||||||
@ -715,43 +690,86 @@ def ReplaceBookmarkWithImage(data_array):
|
|||||||
height = data["height"]
|
height = data["height"]
|
||||||
file_type = data["fileType"]
|
file_type = data["fileType"]
|
||||||
|
|
||||||
if bookmark_name in bookmarks:
|
# 检查书签是否存在
|
||||||
# 获取书签的锚点
|
if bookmark_name not in bookmarks:
|
||||||
|
print(f"错误: 书签 '{bookmark_name}' 不存在")
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 解码 Base64 数据
|
||||||
|
image_bytes = base64.b64decode(image_data)
|
||||||
|
if not image_bytes:
|
||||||
|
raise ValueError("Base64 数据为空或无效")
|
||||||
|
|
||||||
|
# 获取书签的文本范围和光标
|
||||||
bookmark = bookmarks[bookmark_name]
|
bookmark = bookmarks[bookmark_name]
|
||||||
text_range = bookmark.getAnchor()
|
text_range = bookmark.getAnchor()
|
||||||
text_cursor = text_range.getText().createTextCursorByRange(text_range)
|
text_cursor = text_range.getText().createTextCursorByRange(text_range)
|
||||||
|
|
||||||
# 解码Base64图片数据
|
# 记录书签位置并删除书签内容
|
||||||
image_bytes = base64.b64decode(image_data)
|
text = text_range.getText()
|
||||||
image_stream = io.BytesIO(image_bytes)
|
text_cursor.setString("") # 删除书签范围内的文本
|
||||||
|
|
||||||
# 创建PropertyValue对象
|
# 使用临时文件方式插入图片
|
||||||
url_prop = PropertyValue()
|
temp_file_path = None
|
||||||
url_prop.Name = "URL"
|
try:
|
||||||
url_prop.Value = "private:stream"
|
with tempfile.NamedTemporaryFile(delete=False, suffix=f".{file_type}") as temp_file:
|
||||||
|
temp_file.write(image_bytes)
|
||||||
|
temp_file_path = temp_file.name
|
||||||
|
|
||||||
input_stream_prop = PropertyValue()
|
file_url = systemPathToFileUrl(temp_file_path)
|
||||||
input_stream_prop.Name = "InputStream"
|
url_prop = PropertyValue()
|
||||||
input_stream_prop.Value = image_stream
|
url_prop.Name = "URL"
|
||||||
|
url_prop.Value = file_url
|
||||||
|
|
||||||
mime_type_prop = PropertyValue()
|
graphic_properties = (url_prop,)
|
||||||
mime_type_prop.Name = "MimeType"
|
graphic = graphic_provider.queryGraphic(graphic_properties)
|
||||||
mime_type_prop.Value = f"image/{file_type}"
|
|
||||||
|
|
||||||
# 将PropertyValue对象放入序列中
|
if not graphic:
|
||||||
graphic_properties = (url_prop, input_stream_prop, mime_type_prop)
|
raise RuntimeError(f"无法为书签 '{bookmark_name}' 生成图形对象")
|
||||||
|
|
||||||
# 查询图形
|
|
||||||
graphic = graphic_provider.queryGraphic(graphic_properties)
|
|
||||||
|
|
||||||
# 创建图形对象
|
# 创建图形对象
|
||||||
graphic_object = doc.createInstance("com.sun.star.text.TextGraphicObject")
|
graphic_object = doc.createInstance("com.sun.star.text.TextGraphicObject")
|
||||||
graphic_object.Graphic = graphic # 设置图形属性
|
graphic_object.Graphic = graphic
|
||||||
graphic_object.Width = width # 设置宽度
|
graphic_object.Width = width
|
||||||
graphic_object.Height = height # 设置高度
|
graphic_object.Height = height
|
||||||
|
|
||||||
# 替换书签为图片
|
# 设置锚定方式
|
||||||
text_cursor.getText().insertTextContent(text_cursor, graphic_object, False)
|
graphic_object.AnchorType = AS_CHARACTER # 锚定为字符
|
||||||
|
|
||||||
|
# 插入图片
|
||||||
|
text.insertTextContent(text_cursor, graphic_object, False)
|
||||||
|
|
||||||
|
if bookmark_name not in doc.getBookmarks():
|
||||||
|
# 重新创建书签以覆盖图片位置
|
||||||
|
bookmark_range = text.createTextCursorByRange(text_range)
|
||||||
|
new_bookmark = doc.createInstance("com.sun.star.text.Bookmark")
|
||||||
|
new_bookmark.Name = bookmark_name
|
||||||
|
text.insertTextContent(bookmark_range, new_bookmark, False)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# 清理临时文件
|
||||||
|
if temp_file_path and os.path.exists(temp_file_path):
|
||||||
|
os.unlink(temp_file_path)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
continue
|
||||||
|
|
||||||
|
def ExtractBookmarkNames(data):
|
||||||
|
"""
|
||||||
|
从 data["image"] 数组中提取所有 bookmarkName,组成一个字符串数组
|
||||||
|
参数:
|
||||||
|
data: 包含 "image" 键的字典,其值为图片对象数组
|
||||||
|
返回:
|
||||||
|
list: 包含所有 bookmarkName 的字符串数组
|
||||||
|
"""
|
||||||
|
if "image" not in data or not isinstance(data["image"], list):
|
||||||
|
return []
|
||||||
|
|
||||||
|
# 使用列表推导式提取 bookmarkName
|
||||||
|
bookmark_names = [item["bookmarkName"] for item in data["image"] if "bookmarkName" in item]
|
||||||
|
return bookmark_names
|
||||||
|
|
||||||
def GetBookmarksInLists():
|
def GetBookmarksInLists():
|
||||||
"""
|
"""
|
||||||
@ -793,5 +811,4 @@ g_exportedScripts = (
|
|||||||
SaveDocument,
|
SaveDocument,
|
||||||
NextEditableZone,
|
NextEditableZone,
|
||||||
GetBookmarksInLists,
|
GetBookmarksInLists,
|
||||||
SetDocumentToFormMode
|
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user