如何通过 UNO 存储每个打开文档的瞬态数据?

Posted

技术标签:

【中文标题】如何通过 UNO 存储每个打开文档的瞬态数据?【英文标题】:How to store transient data per open document via UNO? 【发布时间】:2018-05-23 08:22:42 【问题描述】:

我有一些配置值(整数和字符串)传递给启动程序,后来在扩展中需要并更改。它们可以在文档之间有所不同,但不能与它们一起保存。

我可以将这些直接存储在 LibreOffice 进程中吗? 无论哪种情况,我都拥有或可以获得对文档的引用 XStorable

到目前为止,我尝试在文档上使用XPropertyContainer.addProperty(...),但我传入的值似乎是全局存储的,而不是每个文档:

XDocumentPropertiesSupplier xDocumentPropertiesSupplier = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, document);
XDocumentProperties xDocumentProperties = xDocumentPropertiesSupplier.getDocumentProperties();
XPropertyContainer xPropertyContainer = xDocumentProperties.getUserDefinedProperties();
xPropertyContainer.addProperty(propertyName, PropertyAttribute.TRANSIENT | PropertyAttribute.MAYBEDEFAULT, propertyValue);

【问题讨论】:

瞬态和可能默认确实意味着:不要在加载文档时存储和使用默认值。删除PropA.TRANSIENT | 可能。 @JoopEggen 抱歉,如果问题不清楚:保存时确实应该在文件中丢弃这些属性。我相当确定我需要为此使用TRANSIENT 是什么让您认为这些值正在全局存储?当我尝试它时(见我的回答),一切都按预期工作。我的猜测是您的代码中存在使用错误文档的错误。 @JimK 事实证明,我在其他地方犯了一个令人尴尬的事后看来的错误。修复它(即在更改文档时实际更新有问题的数据)解决了我的问题。 【参考方案1】:

在下面的python代码中,每个文档的值都不一样,没有存储。

import uno
from com.sun.star.beans.PropertyAttribute import TRANSIENT
from com.sun.star.beans import UnknownPropertyException

def temp_prop():
    DIR = "/path/to/dir"
    LOG1 = DIR + "log1.txt"
    LOG2 = DIR + "log2.txt"
    PROPNAME = "myPropName"
    oDesktop = XSCRIPTCONTEXT.getDesktop()
    oDoc1 = oDesktop.loadComponentFromURL(
        "file:///" + DIR + "1.odt", "_default", 0, ())
    oDoc2 = oDesktop.loadComponentFromURL(
        "file:///" + DIR + "2.odt", "_default", 0, ())
    oDoc1props = oDoc1.getDocumentProperties().getUserDefinedProperties();
    oDoc2props = oDoc2.getDocumentProperties().getUserDefinedProperties();
    try:
        appendToFile(LOG1, oDoc1props.getPropertyValue(PROPNAME))
        appendToFile(LOG2, oDoc2props.getPropertyValue(PROPNAME))
    except UnknownPropertyException:
        appendToFile(LOG1, "Unknown Property")
        appendToFile(LOG2, "Unknown Property")
    oDoc1props.addProperty(PROPNAME, TRANSIENT, "a")
    oDoc2props.addProperty(PROPNAME, TRANSIENT, "b")
    appendToFile(LOG1, oDoc1props.getPropertyValue(PROPNAME))
    appendToFile(LOG2, oDoc2props.getPropertyValue(PROPNAME))
    oDoc1.store()
    oDoc2.store()
    oDoc1props = oDoc1.getDocumentProperties().getUserDefinedProperties();
    oDoc2props = oDoc2.getDocumentProperties().getUserDefinedProperties();
    appendToFile(LOG1, oDoc1props.getPropertyValue(PROPNAME))
    appendToFile(LOG2, oDoc2props.getPropertyValue(PROPNAME))

def appendToFile(fname, s):
    with open(fname, "a") as f: 
        f.write(s + ",")

结果:

logfile1: Unknown Property,a,a,
logfile2: Unknown Property,b,b,

当关闭文档然后再次运行代码时,会出现完全相同的结果,证明没有存储该属性。

【讨论】:

以上是关于如何通过 UNO 存储每个打开文档的瞬态数据?的主要内容,如果未能解决你的问题,请参考以下文章

Grails 域中的瞬态属性

TransientPropertyValueException:对象引用了未保存的瞬态实例 - 在刷新之前保存瞬态实例

如何使用 UNO 获取打开的文档?

数据未保存:对象引用了未保存的瞬态实例 - 在刷新之前保存瞬态实例 [重复]

可以使用反射获得类中的瞬态字段吗

CoreData 中的瞬态属性