图片看不清楚?请点击这里查看原图(大图)'这几天在网上看到了些提取PPT内SWF思路方法于是编程实现了下其他几种OFFICE文件内嵌后基本都可以用另存网页方式解决
'思路是这样:
'1、通过PPTCOM对象遍历幻灯片内容并把找到内嵌SWFControl控件复制到剪贴板
'2、访问剪贴板对象提取其中嵌入对象内容得到个流
'3、处理这个流前面多余部分并保存为文件
'还存在些问题:
'1、如果只有Control控件而没有SWF被嵌入不知道代码会得到如何样结果
经过协商得到了个比较满意结果公开部分代码和软件Software但请遵循协议~~~~~~
请注意这里所提到“内嵌”指将SWF文件内置于OFFICE文件中即在设计文档时将Flash AXControl控件Embed Move属性设置为True
图片看不清楚?请点击这里查看原图(大图)
然后保存文件若要在excel中观看到动画请退出设计模式(点那个 3角板、铅笔、直尺组成图标使的处于非选中状态)
而后是编码了首先是个总体方式:
Private Sub Button2_Click(ByVal sender As .Object, ByVal e As .EventArgs) Handles Button2.Click
Dim file As New OpenFileDialog
file.Filter = "*.XLS|*.XLS"
file.ShowDialog
If file.FileName <> "" Then
AddHandler MSExcel.Progress, AddressOf Progress
MSExcel.GetSWFFile(file.FileName)
RemoveHandler MSExcel.Progress, AddressOf Progress
End If
End Sub
Private Sub Progress(ByVal Msg As String)
lstMsg.Items.Add(Msg)
End Sub
在按钮点击事件个打开文件对话框以打开要提取SWF文件XLS文档而后为了显示进度消息添加事件处理句柄到 Progress当使用完毕后该句柄被移除而Progress是非常简单仅仅在个名为lstMsgListBox里面添加得到消息
接下来实现GetSWFFile这个被设定在个仅有共享成员类(MSExcel)中该类将有个共享成员:
Public Shared Event Progress(ByVal Msg As String)
而为了以后扩展需要把进程和文档引用都放在了这里:
Private Shared app As Excel.Application
Private Shared book As Excel.Workbook
当然为了使用这些代码需要在类文件开头导入个名空间在这里使用了指定别名方式:
Imports Excel = Microsoft.Office.Interop.Excel
(请在引用对话框添加Microsoft.Office.Interop.Excel.XX及相应版本OFFICE.NET引用在这里笔者使用是 OFFICE2003所以添加版本都为11OFFICE引用当中会包含些名空间而对于我们来讲只使用了其中包含些常量名空间所以你完全可以用相应数字来代替这些常量而不引用名空间这样做好处后面还将叙述)
而后编写个实现复制FLASH内嵌对象、个将剪贴板内容保存为SWF文件(将这个功能分离是它可以重用:在其他OFFICE文件格式处理时也用这个)首先描述第个这个要实现功能就是把XLS文件中FLASH OLE内容复制出来简单做法是利用EXCEL:
1、打开文档:
app = New Excel.Application
app.Visible = Microsoft.Office.Core.MsoTriState.msoTrue(在VBA、VB6、VB.NETIDE中这个msoTrue实际上为-1对于VB.NET布尔型在IDE和CLR中关系等等不想赘述有疑问可以参考VB.NET核心编程或.NET FRAMEWORK详解等在我们里“最终”应使用-1来代替这些常量后面将给予介绍说明)
book = app.Workbooks.Open(file)
2、遍历并复制FLASH OLE内容
这里叙述可能有些小问题不深究了实际上我们操作是复制了FLASHControl控件其他操作由OFFICE自动完成了
A、我们都知道在EXCEL里工作簿里面有N个(默认3个)工作表而我们要FLASH在某个工作表里面所以我们先遍历book这个工作簿Sheets集合而后遍历每个SheetShapes集合从而达到遍历Shape目
For i As Integer = 1 To book.Sheets.Count
For j As Integer = 1 To book.Sheets(i).Shapes.count
‘这里进行识别
Next
Next
B、当得到Shape引用的后我们就要识别它是否包含了FLASHOLE内容这个内容如何识别呢我们知道OLE对象都有个OLEFormat属性它包含了OLE信息其中ProgID属性是个很有用串包括了OLE对象类型我们使用这个属性来识别:
If InStr(1, book.Sheets(i).Shapes(j).OLEFormat.ProgID, "ShockwaveFlash.ShockwaveFlash", vbTextCompare) = 1 Then
’这里执行复制代码
End If
C、当我们得到了含有FLASH OLEShape对象引用的后就可以复制它在区别OFFICE工具中复制思路方法可能有些差异但在EXCEL中我们对象是Shape它支持COPY思路方法于是我们直接复制:
'是FLASH内嵌文件则复制到剪贴板
book.Sheets(i).Shapes(j).copy
D、将处理权交给剪贴板处理:
Clipboard2File(book.Name, i, j)
这个有 3个参数:第个是处理文件名第2、3个是我们遍历时用到数据其实这 3个参数都是为了命名最终生成文件而传入如果有必要你可以把这个保存文件功能分离出来——也许这样更好但是我没有这样做理由就是……我懒
3、剪贴板处理:
就是我们上面Clipboard2File了我把它放在个类(Clipboard2FileClass)里面这个类仅有个共享成员:我们处理
这里我们使用是Clipboard对象来读取剪贴板数据:
Dim iData As IDataObject = Clipboard.GetDataObject
这都是大家所熟知东东了用它就可以读回来我们要内容但是内容格式是什么呢?当然是“内嵌对象”了呵呵
Dim ms As IO.MemoryStream = iData.GetData("Embedded Object")
于是我们就得到个含有SWF文件内容流——它是我们复制到内存中全部数据部分也正是我们关心SWF文件所在部分到这里有种即将大功告成希望了吧?也许没什么好高兴我们共才写了几十行代码?
接下来处理这个流如何提取SWF文件是当务的急如果我们熟知SWF文件结构该有多好……(……)(*(——&*%……¥%……¥)(()——(
确实已经有同志付出了很多努力给了我们个母语版SWF文件结构对此表示敬意对原作者表示感谢!
http://bbs.zhujiangroad.com/html/2008/6/250234.html
上面地址就是了~~~~~我们要用信息就是前8字节:
1
2 FWS,CWS
3
4 版本
5
6 文件大小
7
8
OK开始找文件头吧!这个内存流查找我还真不会转化成而后遍历
Dim bs As Byte = ms.ToArray '将原始流转化为以对SWF文件头进行搜索
Dim po As Integer '文件头位置
For index As Integer = 0 To bs.Length - 3
If bs(index) = CByte(&H46) OrElse bs(index) = CByte(&H43) Then '有两种情况可能是
SWF,也可能是SWC视FLASH生成文件时是否压缩
If bs(index + 1) = CByte(&H57) AndAlso bs(index + 2) = CByte(&H53) Then
po = index
Exit For
End If
End If
Next
这样我们po里面保存就是SWF文件开始位置了~~再得到文件长度就可以把写入个新流而后保存
Dim filesize As Integer = .BitConverter.ToInt32(bs, po + 4)
Dim by As New IO.MemoryStream(bs, po, filesize)
此时by流中就是我们SWF文件保存它!
Dim filename As String = My.Application.Info.DirectoryPath & "\SWFFile\" & name & "-" & i & "-" & j & ".swf"
If Not My.Computer.File.DirectoryExists(My.Application.Info.DirectoryPath & "\SWFFile\") Then My.Computer.File.CreateDirectory(My.Application.Info.DirectoryPath & "\SWFFile\")
If My.Computer.File.FileExists(filename) Then My.Computer.File.DeleteFile(filename)
'创建个流以保存内存流到磁盘
Dim dumpFile As IO.FileStream = New IO.FileStream(filename, IO.FileMode.OpenOrCreate, IO.FileAccess.ReadWrite)
'保存内存流
by.WriteTo(dumpFile)
上面过程进行了文件夹和文件是否存在等判断和操作以保证“健壮”——不能个文件操作搞得崩溃了啊多丢人呵呵最后擦擦屁屁:
'退出用过流
dumpFile.Close
ms.Close
by.Close
'清除剪贴板
My.Computer.Clipboard.Clear
好了至此我们EXCEL中提取SWF工作告段落你可以测试你代码了……感觉还不错吧?连注释都算进去不到百行解决了这个问题
下面是个测试文件和写好主但使用时有些限制如果仔细阅读了上文相信你已经知道如何做~~~~
/Files/zcsor/提取SWF工具测试文件.xls
/Files/zcsor/复制OFFICE内嵌SWF.7z
最后最后我们来讨论下这个代码存在问题~~~适应性为了让更多OFFICE版本被我们支持你可以进行以下工作~~~(当然我没做懒啊)
0、复制份解决方案目录打开这个复制品
1、用鼠标指着每个OFFICE常量它怕怕了就把实际数值告诉你用数值替换这些常量
2、将APP和BOOK声明为OBJCET并改用CreateObject 思路方法创建APP对象
3、在引用页扫描未使用引用并删除它们
OK你更通用版本诞生了~~~~可回到IDE修改代码时就没有那么多提示喽~~~~~~呵呵呵并不是我们不知道如何做更好如何才能做到更好是吧?
最新评论