ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 11087|回复: 20

[求助] vba打开文件之后怎么释放内存?守柔等大侠请帮忙

[复制链接]

TA的精华主题

TA的得分主题

发表于 2015-1-16 17:32 | 显示全部楼层 |阅读模式
本帖最后由 loquat 于 2015-1-16 17:34 编辑

Sub 文件修改_加报告编号()
Application.ScreenUpdating = False
Application.DisplayAlerts = wdAlertsNone
Dim strPath$, arr, aName$, aPath$, bName$, 报告编号$
Dim fso As New Scripting.FileSystemObject
Dim aMin&, aMax&, i&
strPath = "D:\工作\*.doc"
With CreateObject("WScript.Shell")
       'arr = .Exec(Environ$("comspec") & " /c dir " & Chr(34) & strPath & Chr(34) & " /s /a:-d /b | findstr /v " & Chr(34) & "DL-14" & Chr(34)).StdOut.ReadAll
       .Run Environ$("comspec") & " /c dir " & Chr(34) & strPath & Chr(34) & " /s /a:-d /b | findstr /v " & Chr(34) & "DL-14" & Chr(34) & " | findstr /v " & Chr(34) & "~" & Chr(34) & " > C:\temp.txt", 0, True
End With
aNum = FreeFile
Open "C:\temp.txt" For Input As #aNum
    arr = Split(StrConv(InputB(LOF(aNum), aNum), vbUnicode), vbCrLf)
Close #aNum
aMin = LBound(arr)
aMax = UBound(arr)
For i = aMin To aMax
    aPath = "": aName = "": 报告编号 = "": bName = ""
    With Documents.Open(arr(i))   ‘这里开始占用内存
        报告编号 = aDoc.Bookmarks("_报告编号").Range.Text
        .UndoClear
        .Close False  '关闭文件时不会释放内存
    End With          '这里还是没有释放
    ActiveDocument.UndoClear  '这里也没有释放
    aPath = fso.GetParentFolderName(arr(i)) & "\"
    aName = fso.GetBaseName(arr(i))
    bName = aPath & "New\" & aName & "_" & 报告编号 & "-.doc"
    fso.CopyFile arr(i), bName
Next i
Application.DisplayAlerts = wdAlertsAll
Application.ScreenUpdating = True
End Sub
那问题来了,要怎样才能释放内存呢?

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-1-16 22:05 | 显示全部楼层
现在能想到的唯一方案是新建Word.Application(即新建进程)
在循环一次或者指定次数之后就关闭新建进程,然后重新新建进程。
这样就印象效率一点。但是不会吃内存。。。

TA的精华主题

TA的得分主题

发表于 2015-1-23 10:06 | 显示全部楼层
loquat 发表于 2015-1-16 22:05
现在能想到的唯一方案是新建Word.Application(即新建进程)
在循环一次或者指定次数之后就关闭新建进程,然 ...

To loquat兄:
你所指的占用内存情况,是如何获得的?
理论上说,每次打开一个Word文档时(后),肯定是要消耗一定内存的,关闭该文档后,由这个文档引起的内存Word应该会自动释放.我不知道您是使用何种方法监控到内存未释放?
通常而言,使用一个Document对象,为Open方法打开的对象赋值,然后关闭,再强制设置为Nothing,看是否释放了?
其次,调试每一个打开的Document对象,在Close后,VBE的资源管理器中,该文档是否已被"卸载";
第三,是否你的每个Word文档中,包含了较多的域,特别是EQ域的情况?因为我之前发现如果WORD文档中有较多EQ域(如拼音指南等),则Word会消耗较多的内存,且即使关闭该文档(前台操作即可重现),Word在一段时间内,其内存在任务管理器中查看,仍居高不下,Word 2003中忧甚.

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-1-23 13:59 | 显示全部楼层
守柔 发表于 2015-1-23 10:06
To loquat兄:
你所指的占用内存情况,是如何获得的?
理论上说,每次打开一个Word文档时(后),肯定是要消耗 ...

>1. 老大,我是在系统进程管理器中发现没有释放内存的。VBE中在红字部分都设定了断点。
>2. 我试过了,强制设置为Nothing似乎也无效。。。
>3. 我打开的文档中是有比较多的域

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-1-23 15:05 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2015-1-23 15:59 | 显示全部楼层
loquat 发表于 2015-1-23 13:59
>1. 老大,我是在系统进程管理器中发现没有释放内存的。VBE中在红字部分都设定了断点。
>2. 我试过了,强 ...

既是如此,不妨这样,在Word VBA中:
先创建一个New Word.APPlication进程(也可以CreateObject),打开所有文档后,再释放这个进程吧.有些问题太复杂,不是Word VBA自身可以简单解决的.

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-1-23 18:31 来自手机 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
守柔 发表于 2015-1-23 15:59
既是如此,不妨这样,在Word VBA中:
先创建一个New Word.APPlication进程(也可以CreateObject),打开所有文 ...

是的,现在我找到的解决方案也是这个。
再请问老大vba下有没有较稳定的多线程,或者过程的异步执行方案。

TA的精华主题

TA的得分主题

发表于 2015-1-23 20:39 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
守柔好久不见你在论坛了,这些年你还在研究word吗,我这些年一直在研究word?
上面这个问题我也曾经研究过,从word内部解决,多种思路都解决不了,上面讨论的都解决不了或者解决不好,新开word进程在效率上的牺牲可能比内存上的牺牲更不可以接受,不知道你们是否有更好的方法。
我弄了一个从外面处理word的例子,不知道是否可以满足loquat的需要。

内存清理.rar

7.06 KB, 下载次数: 115

TA的精华主题

TA的得分主题

发表于 2015-1-24 07:29 | 显示全部楼层
本帖最后由 守柔 于 2015-1-24 07:31 编辑
cuteword 发表于 2015-1-23 20:39
守柔好久不见你在论坛了,这些年你还在研究word吗,我这些年一直在研究word?
上面这个问题我也曾经研究过 ...


谢谢cuteword兄的惦记。
有很长一段时间,不再关注论坛了,但其实一直没有离开EH。
现在一直在从事EH的技术服务工作,对Word的研究少了,更多的精力是在对Excel进行开发。

回到话题本身。
创建多个New Word.Application进程,得不偿失。你的“内存清理”我先收下,效果如何,目前没有测试条件,不好说。
从楼主本意而言,是取得Word文档的指定书签内容,然后复制文件。我提供一个新的思路,请楼主测试一下,是否更合适。

简单的录了一个宏:
    Selection.InsertFile FileName:="Excel追价宝.docx", Range:="myBookMark", ConfirmConversions:=False, Link:=False, Attachment:=False
它的意思是在当标位置插入指定文件中的特定范围(书签)的文字。

有籍于此,可适当修改一部分代码。
即向当前文档插入这个书签(因书签是已知的),再返回Content.Text(每次覆盖),即可得到该书签中的文字(报告编号)。感觉Word可能不会直接打开这个文档再返回书签内容的。
请楼主测试后反馈之。

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-1-24 10:03 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 loquat 于 2015-1-24 12:49 编辑
cuteword 发表于 2015-1-23 20:39
守柔好久不见你在论坛了,这些年你还在研究word吗,我这些年一直在研究word?
上面这个问题我也曾经研究过 ...

1.龚老师的这个代码确实有效,请问是不是使用的API函数SetProcessWorkingSetSize?
  老师的这个程序的确解决了word出现问题,此操作完成后将无法撤销的问题。。。原来我运行90次左右循环就会出现以上提示框。  我原来的解决方案是强制后台执行按键“是(Y)”,   现在有了老师的小程序,改为后台执行老师程序的“Word”。  现在能执行循环到200次左右。。。
2.守柔大哥的代码让我学到一招,我稍后测试看看内存占用。不过归根到底小弟是想解决像上面红色部分的问题类似的问题。。。
   关键是内存释放。。。
3.另发一个微软官方的命令行程序,可以实现龚老师一样的效果。。。

    empty.rar (4.51 KB, 下载次数: 123)
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-23 15:45 , Processed in 0.039693 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表