- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我已经编写了一个 python 脚本,它将作为我支持的启用宏的 PowerPoint 文件的“构建脚本”。
该脚本创建一个新的空 PowerPoint 演示文稿,导入所有 VBA 模块,保存文件并将其转换为 ZIP 存档,以便插入 RibbonUI 配置 (ribbon_xml.xml文件和 mylogo.jpg 文件)。
所有这些都或多或少地按预期工作——直到我尝试使用输出文件(手动将 .zip 重命名为 .pptm 并在 PowerPoint 中打开它)。
错误代码完全退出,但输出存档 (copy.zip) 在转换为 PPTM 文件时无法正常打开。
我收到配置有问题的警告,PowerPoint 将尝试修复该文件。
PowerPoint,就其本质而言,当然并没有指出问题所在,只是它发现了“不可读的内容”并且此类内容已“被删除”......我在比较一些文件后唯一能看到的我手动创建的是 CustomUI 的 XML 属性似乎使用某种 GUID 作为其 id 属性的一部分
当前的解决方法:函数 build_ribbon 可以使用 CustomUI Editor 工具手动完成,大约需要 3 分钟才能可靠地生成 PPTM 输出。
所以这不是一个特别的“Python”问题,因为它是一个关于 CustomUI XML/ribbon XML 接口(interface)的实现的问题。
完整代码:
import win32com.client
import os
import zipfile
import uuid
#### PARAMETERS
vba_source_control_path = r"C:\Repos\MyAddIn\VBA\ChartBuilder_PPT\Modules"
output_path = r"C:\debug\output.pptm"
ribbon_xml_path = r"C:\Repos\MyAddIn\Ribbon XML\ribbon_xml.xml"
ribbon_logo_path = r"C:\Repos\MyAddIn\Ribbon XML\mylogo.jpg"
def build_addin(pres, path):
"""
This procedure does the following:
1. adds all of the VBComponents to the working PPTM file
The .PPTM file is used for local development & debugging and
is only usually packaged as a PPAM for Testing and Distribution
"""
for fn in [fn for fn in os.listdir(path) if not(fn.endswith(".frx"))]:
pres.VBProject.VBComponents.Import(path + "\\" + fn)
# Clean up old files, if any
if os.path.isfile(output_path):
os.remove(output_path)
if os.path.isfile(output_path.replace(".pptm", ".zip")):
os.remove(output_path.replace(".pptm", ".zip"))
# Save the new file with VBProject components
pres.SaveAs(output_path)
pres.Close()
def build_ribbon_zip():
"""
build_ribbon_zip handles manipulation of the .ZIP contents and places the
necessary components within the PPTM ZIP archive structure
2. converts the PPTM to a .ZIP
3. Adds the CustomUI XML and logo.jpg to the .ZIP directory
4. converts the .ZIP to a PPTM
"""
id = '<Relationship Id='
schema = 'http://schemas.openxmlformats.org/officeDocument/2006/'
_path = output_path.replace(".pptm", ".zip")
copy_path = r"C:\debug\copy.zip"
# Convert to ZIP archive
os.rename(output_path, _path)
zip = zipfile.ZipFile(_path, 'a')
copy = zipfile.ZipFile(copy_path, 'w')
guid = str(uuid.uuid4()).replace('-', '')[:16]
for itm in [itm for itm in zip.infolist() if itm.filename != r'_rels/.rels']:
buffer = zip.read(itm.filename)
copy.writestr(itm, buffer)
# Append the Logo file to the .zip and create the archive
copy.write(ribbon_logo_path, r'\CustomUI\images\jdplogo.jpg')
# append the CustomUI xml part to the .zip and create the archive
copy.write(ribbon_xml_path, r'\CustomUI\customUI14.xml')
# append the .rels file to CustomUI\_rels
rels_xml = r'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
rels_xml += r'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
rels_xml += r'<Relationship Id="jdplogo" Type="'+schema+'relationships/image" Target="images/jdplogo.jpg"/>'
rels_xml += r'</Relationships>'
copy.writestr(r'CustomUI\_rels\customUI14.xml.rels', rels_xml.encode('utf-8'))
# get the existing _rels/.rels XML content and append the UI:
rels_xml = zip.read(r'_rels/.rels').rstrip()[:-16]
rels_xml += id + r'"R'+guid+'" Type="http://schemas.microsoft.com/office/2007/relationships/ui/extensibility"'
rels_xml += r'Target="customUI/customUI14.xml"/></Relationships>'
rels_xml = rels_xml.replace(os.linesep, '')
# this file-like object is read-only, and the writestr method will create another .rels file...
copy.writestr(r'_rels/.rels', rels_xml.encode('utf-8'))
zip.close()
copy.close()
if __name__ == "__main__":
"""
Procedure to create a new PowerPoint Presentation and insert the Code Modules from source control
"""
ppApp = win32com.client.Dispatch("PowerPoint.Application")
pres = ppApp.Presentations.Add(False)
pres.Slides.AddSlide(1, pres.SlideMaster.CustomLayouts(1))
build_addin(pres, vba_source_control_path)
ppApp.Quit()
build_ribbon_zip()
最佳答案
输出中缺少一些引用,导致 PowerPoint 异常。像这样解决这个问题:
def build_addin(pres, path):
"""
This procedure does the following:
1. adds all of the VBComponents to the working PPTM file
2. adds required project references
The .PPTM file is used for local development & debugging and
is only usually packaged as a PPAM for Testing and Distribution
"""
version = str(int(float(pres.Application.version)))
# import the VB Components
for fn in [fn for fn in os.listdir(path) if not(fn.endswith(".frx"))]:
pres.VBProject.VBComponents.Import(path + "\\" + fn)
# add the required project references
pres.VBProject.References.AddFromFile(r'C:\Program Files (x86)\Microsoft Office\Office'+version+'\EXCEL.EXE')
# MSForms TreeView Control
pres.VBProject.References.AddFromFile(r'C:\Windows\SysWOW64\MSCOMCTL.OCX')
# MSXML2
pres.VBProject.References.AddFromFile(r'C:\Windows\System32\msxml6.dll')
# ADODB
pres.VBProject.References.AddFromFile(r'C:\Program Files (x86)\Common Files\System\ado\msado15.dll')
# VBE Extensibility
我还在 build_ribbon
中发现了一些可能格式错误的 XML 并修复了它,但仍然不是 100%,因为 PowerPoint 在第一次打开(一次)时仍然需要“修复”文件,但之后那,它似乎按预期工作。
我注意到自定义 Logo 没有出现在功能区中,我发现“不可读的内容”可能与加载到其中一个功能区控件上的 JPG 图像文件有关。来自 this forum on OpenXMLDeveloper :
This kind of problem occurs when there is an issue in one of the following areas.
- Relationship Id does not match with parts
- Error in content_types.xml file
- Error in parts (document.xml or any other parts)
- Mismatched link between slide master-slide layout/slide layout-slide
我仔细检查了 [Content_Types].xml 文件不包含 .jpg 文件扩展名的元素。
我为 ElementTree 添加导入语句:
import xml.etree.ElementTree as ET
然后修改build_ribbon_zip
如下:
def build_ribbon_zip():
"""
build_ribbon_zip handles manipulation of the .ZIP contents and places the
necessary components within the PPTM ZIP archive structure
3. converts the PPTM to a .ZIP
4. Adds the CustomUI XML to the .ZIP directory
5. converts the .ZIP to a PPTM
"""
bom = u'\ufeff'
_path=output_path.replace('.pptm', '.zip')
copy_path=r'C:\debug\copy.zip'
# Convert to ZIP archive
os.rename(output_path, _path)
z=zipfile.ZipFile(_path, 'a', zipfile.ZIP_DEFLATED)
copy=zipfile.ZipFile(copy_path, 'w', zipfile.ZIP_DEFLATED)
guid=str(uuid.uuid4()).replace('-', '')[:16]
"""
the .rels files are written directly from XML string built in procedure
the [Content_Types].xml file needs to include additional parameter for the 'jpg' extension
"""
for itm in [itm for itm in z.infolist() if itm.filename != r'_rels/.rels']:
buffer = z.read(itm.filename)
if itm.filename == "[Content_Types].xml":
# Modify the [Content_Types].xml file to include the jpg reference
# <Default Extension="jpg" ContentType="image/.jpg" />
# copy the XML from the original zip archive, this file has not been copied in the above loop
root = ET.fromstring(buffer)
ET.SubElement(root, '{http://schemas.openxmlformats.org/package/2006/content-types}Default', {'Extension': 'jpg', 'ContentType': 'image/.jpg'})
copy.writestr(itm, ET.tostring(root).encode('utf-8'))
# Append the Logo file to the .zip and create the archive
copy.write(ribbon_logo_path, r'\customUI\images\jdplogo.jpg')
else:
copy.writestr(itm, buffer)
# append the CustomUI xml part to the .zip and create the archive
copy.write(ribbon_xml_path, r'\customUI\customUI14.xml')
# create the string & append the .rels to CustomUI\_rels
rels_xml = """<?xml version="1.0" encoding="utf-8"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="images/jdplogo.jpg" Id="jdplogo" />
</Relationships>"""
copy.writestr(r'customUI\_rels\customUI14.xml.rels', rels_xml.encode('utf-8'))
# get the existing _rels/.rels XML content and copy to the copied archiveI:
rels_xml = r'<?xml version="1.0" encoding="utf-8" ?>'
rels_xml += r'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
rels_xml += r'<Relationship Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/'
rels_xml += r'core-properties" '
rels_xml += r'Target="docProps/core.xml" Id="rId3" />'
rels_xml += r'<Relationship Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail" '
rels_xml += r'Target="docProps/thumbnail.jpeg" Id="rId2" />'
rels_xml += r'<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" '
rels_xml += r'Target="ppt/presentation.xml" Id="rId1" />'
rels_xml += r'<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" '
rels_xml += r'Target="docProps/app.xml" Id="rId4" /><Relationship '
rels_xml += r'Type="http://schemas.microsoft.com/office/2007/relationships/ui/extensibility" '
rels_xml += r'Target="/customUI/customUI14.xml" Id="R'+guid+'" /></Relationships>'
copy.writestr(r'_rels\.rels', rels_xml.encode('utf-8'))
z.close()
copy.close()
os.remove(_path)
os.rename(copy_path, output_path)
关于用于 VBA 加载项文件的 Python 构建脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31664821/
我在为 MacOSX 构建的独立包中添加 DMG 背景的自定义图标时遇到问题。我在项目的根目录中添加了一个包。正在从中加载自定义图标,但没有加载 DMG 背景图标。我正在使用 Java fx 2.2.
Qt for Symbian 和 Qt for MeeGo 有什么区别?我知道 Qt 是一个交叉编译平台。这是否意味着如果我使用来自 Qt 的库,完全相同的库可以在所有支持 Qt 的设备(例如 Sym
我正在尝试使用 C# .NET 3.5/4.0 务实地运行 SQL Server 数据库的备份。我已经找到了如何完成此操作,但是我似乎找不到用于备份的命名空间库。 我正在寻找 Microsoft.Sq
我最近在疯狂学习 Java,但我通常是一名 .NET 开发人员。 (所以请原谅我的新手问题。) 在 .Net 中,我可以在不使用 IIS 的情况下开发 ASP.Net 页面,因为它有一个简化的 Web
这post仅当打印命令中有字符串时才有用。现在我有大量的源代码,其中包含一条声明,例如 print milk,butter 应该格式化为 print(milk,butter) 用\n 捕获行尾并不成功
所以我的问题是: https://gist.github.com/panSarin/4a221a0923927115584a 当我保存这个表格时,我收到了标题中的错误 NoMethodError (u
如何让 Html5 音频在点击时播放声音? (ogg 用于 Firefox 等浏览器,mp3 用于 chrome 等浏览器) 到目前为止,我可以通过 onclick 更改为单个文件类型,但我无法像在普
如果it1和it2有什么区别? std::set s; auto it1 = std::inserter(s, s.begin()); auto it2 = std::inserter(s, s.en
4.0.0 com.amkit myapp SpringMVCFirst
我目前使用 Eclipse 作为其他语言的 IDE,而且我习惯于不必离开 IDE 做任何事情 - 但是我真的很难为纯 ECMAScript-262 找到相同或类似的设置。 澄清一下,我不是在寻找 DO
我想将带有字符串数组的C# 结构发送到C++ 函数,该函数接受void * 作为c# 结构和char** 作为c# 结构字符串数组成员。 我能够将结构发送到 c++ 函数,但问题是,无法从 c++ 函
我正在使用动态创建的链接: 我想为f:param附加自定义转换器,以从#{name}等中删除空格。 但是f:param中没有转换器
是否可以利用Redis为.NET创建后写或直写式缓存?理想情况下,透明的高速缓存是由单个进程写入的,并且支持从数据库加载丢失的数据,并每隔一段时间持久保存脏块? 我已经搜查了好几个小时,也许是goog
我正在通过bash执行命令的ssh脚本。 FILENAMES=( "export_production_20200604.tgz" "export_production_log_2020060
我需要一个正则表达式来出现 0 到 7 个字母或 0 到 7 个数字。 例如:匹配:1234、asdbs 不匹配:123456789、absbsafsfsf、asf12 我尝试了([a-zA-Z]{0
我有一个用于会计期间的表格,该表格具有期间结束和开始的开始日期和结束日期。我使用此表来确定何时发生服务交易以及何时在查询中收集收入,例如... SELECT p.PeriodID, p.FiscalY
我很难为只接受字符或数字的 Laravel 构建正则表达式验证。它是这样的: 你好<-好的 123 <- 好的 你好123 <-不行 我现在的正则表达式是这样的:[A-Za-z]|[0-9]。 reg
您实际上会在 Repeater 上使用 OnItemDataBound 做什么? 最佳答案 “此事件为您提供在客户端显示数据项之前访问数据项的最后机会。引发此事件后,数据项将被清空,不再可用。” ~
我有一个 fragment 工作正常的项目,我正在使用 jeremyfeinstein 的 actionbarsherlock 和滑动菜单, 一切正常,但是当我想自定义左侧抽屉列表单元格时,出现异常
最近几天,我似乎平均分配时间在构建我的第一个应用程序和在这里发布问题!! 这是我的第一个应用程序,也是我们的设计师完成的第一个应用程序。我试图满足他所做的事情的外观和感觉,但我认为他没有做适当的事情。
我是一名优秀的程序员,十分优秀!