VBScript/VBA批量合并多个Word文件到一个文件

如果手头有一些比较零散的Office Word文件(*.DOC),但是实际需求确实要将这些Word文件合并成一个Word文件,假如说这些零散的文件比较多,那么手工一个一个添加必定会带来麻烦。这时我们就可以使用VBA的相关功能来帮助我们了。

Const wdPageBreak = 7 ' 分页符

Dim strFileName
strFileName = "要合并的文件.doc"

Dim strDestFileName
strDestFileName = "最终合并的文件.doc"

Dim wdApp, doc, Selection
Set wdApp = WSH.CreateObject("Word.Application")
wdApp.Visible = False

Set doc = wdApp.Documents.Add

Set Selection = wdApp.Selection
' 这里strFileName直接是要合并的文件路径
' Selection.InsertFile FileName:=strFileName
Selection.InsertFile strFileName
' 跳转到下一页(插入分页符)
' Selection.InsertBreak Type:=wdPageBreak
Selection.InsertBreak wdPageBreak

Set doc = Nothing
doc.SaveAs strDestFileName
doc.Close

Set doc = Nothing
wdApp.Visible = True
wdApp.Quit
Set wdApp = Nothing

上面的代码具体演示了如何插入一个文档,那么如何批量插入多个文档呢?你可以试试我前面一篇文章 《采用插件机制的批量文件扫描及进程处理工具》 所介绍的办法,或者像下面这样:

Posted in:
  • VBScript/JavaScript/Python
  • 系统应用程序开发
Tagged
  • vba
  • word
  • vbscript

DECOMPILATION OR DISASSEMBLY PROHIBITED

今天单位里的那台清华同方的电脑无法开机,开机后电脑上显示一行彩色的Intel标志,然后就是一行 DECOMPILATION OR DISASSEMBLY PROHIBITED 和Intel(英特尔)的版权信息,而且这几行信息是在开机第一屏出现的,同时无法进入系统,初步判断是硬件问题,网上找了下相关资料,发现问题集中在内存条、显卡和BIOS的CMOS设置上面。

初步排除内存条和显卡问题,为什么呢?首先开机自检没有任何声响报警,其次无法进入CMOS设置,最后注意到 DECOMPILATION OR DISASSEMBLY PROHIBITED 这句话,这句话的意思是“禁止反编译或拆卸”,反编译是什么,当然是针对软件的,除了硬盘上的Windows以外,主板上BIOS芯片里还烧录了软件程序,那么所有的问题就集中在BIOS程序上面。

BIOS的程序混乱了,只有先采取放电的方法将CMOS设置重置恢复,但愿只是设置问题,如果是芯片被烧毁就麻烦了,打开机箱,找到为CMOS设置供电的大纽扣电池,取下电池,不过貌似没找到放电的触点,那么只有取下电池后等段时间,让其自然放电。完成后,启动电脑,这时电脑显示CPU什么更新,按F1继续,初步证明刚才我的想法是正确的,确实是BIOS的CMOS设置问题,看来问题不大,关闭电脑,将主板上纽扣电池安装回去,再次启动电脑,出现按F1继续的时候,我们按DEL按键进入CMOS设置,如果有Load Default Settings(加载默认配置)的话选择该项,然后Save and exit,保存并退出,这时就能正常进入系统了。

最后我又重新开机关机了几次,均正常,希望以后不要出现这种情况了。

当然出现 DECOMPILATION OR DISASSEMBLY PROHIBITED 这句话也不排除其他问题,我的方法仅供参考。

Posted in:
  • 计算机应用及维护
  • Windows系统
  • Unix/Linux/BSD系统
Tagged
  • 启动故障
  • bios

Word、Excel、PPT、Access等Office VBA编程手册

VBA编程有时确实能帮我们大忙,将我们从繁重枯燥的操作中解放出来,但是相关介绍的文档不是很好找的,如果我们安装有Microsoft Office,那么在安装目录下应该能够找到一份CHM的帮助文档,我将一些关于VBA编程的CHM手册发上来,供大家参考:

  • Word VBA (VbaWord.chm)
  • Excel VBA (Vbaexcelxl10.chm)
  • PowerPoint VBA (VbaPowerPoint.chm)
  • Access VBA (Vbaaccess.chm)

更多的比如Outlook和FrontPage可以点击这里下载获得。

当然,微软还为不愿意下载的我们提供了在线文档,在手边没有手册的情况下可以救救急。 http://msdn.microsoft.com/en-us/library/dd941266(v=office.12).aspx

Posted in:
  • VBScript/JavaScript/Python
  • 系统应用程序开发
Tagged
  • vba
  • 参考手册

VBA对Word行、段落和光标位置的移动、选择和操作

Mr.Abao'S Blog 上看到的,VBA编程时要参考,特地转一下,另外由于嵌入到VBScript脚本中编程,对一些常量我给出了声明:

Const wdCharacter = 1
Const wdExtent = 1
Const wdExtend = 1
Const wdGoToBookmark = -1
Const wdLine = 5
Const wdCell = 12
Const wdTableFormatSimple2 = 2
Const wdAlignParagraphRight = 2
Const wdYellow = 7
Const wdToggle = 9999998
Const wdAlignParagraphCenter = 1
Const wdSentence = 3
Const wdParagraph = 4
Const wdStory = 6
Const wdMove = 0

下面我将 Mr.Abao'S Blog 的内容转帖(略作修改,主要是注释部分增加了VBScript的脚本写法):在WORD中用VBA宏语言选定一行、一段,删除一行、一段,移动光标至行首、行尾、段首、段尾等。

Posted in:
  • VBScript/JavaScript/Python
  • 系统应用程序开发
Tagged
  • vba
  • word

C#利用反射(Reflection)进行SHA1和MD5的哈希(Hash)加密

最近在ASP.NET项目中用到的,主要是对用户密码进行哈希加密,传统编程进行的两种哈希加密方式一般如下:

using System;
using System.Text;
using System.Security.Cryptography;

namespace ConsoleApplication1
{
    class Program
    {
        public static string ComputeSHA1Hash(string str)
        {
            using (SHA1CryptoServiceProvider
                sha1Csp = new SHA1CryptoServiceProvider())
            {
                str = Convert.ToBase64String(
                        sha1Csp.ComputeHash(
                        Encoding.UTF8.GetBytes(str)
                        )
                    );
                sha1Csp.Clear();
            }
            return str;
        }

        public static string ComputeMD5Hash(string str)
        {
            using (MD5CryptoServiceProvider
                md5Csp = new MD5CryptoServiceProvider())
            {
                str = Convert.ToBase64String(
                        md5Csp.ComputeHash(
                        Encoding.UTF8.GetBytes(str)
                        )
                    );
                md5Csp.Clear();
            }
            return str;
        }

        static void Main(string[] args)
        {
            System.Console.WriteLine(ComputeSHA1Hash(@"http://wangye.org"));
            System.Console.WriteLine(ComputeMD5Hash(@"http://wangye.org"));
        }
    }
}

通过代码可以很明显的看出,我们主要引入System.Security.Cryptography的命名空间,然后调用其SHA1CryptoServiceProvider进行SHA1哈希或者调用MD5CryptoServiceProvider进行MD5哈希,当然由于哈希所需要的参数是字节型的,所以还需要将字符串进行一次字节编码,为了更好的兼容性,我们这里选择Encoding.UTF8.GetBytes进行UTF8编码,然后将哈希编码好的字节码再转换为Base64,至此整个哈希编码完成。

大家可能看到这两个函数比较类似,有没有什么办法将它们整合一下,变得更通用呢?对了,你可能想到了反射(Reflection),确实我们可以引入反射机制,从而让我们的代码更精简,更通用。反射功能需要引入System.Reflection命名空间,然后查找SHA1CryptoServiceProvider和MD5CryptoServiceProvider的定义,发现其共同继承了HashAlgorithm这个类,这么说这个类可以作为一个通用的类型。Assembly.GetAssembly().CreateInstance()的方式创建对象,那么GetAssembly()的参数类型该如何获得呢?我们可以通过System.Type.GetType(“命名空间名称”)这个方法得到,比如说System.Type.GetType("System.Security.Cryptography.SHA1CryptoServiceProvider")将得到SHA1CryptoServiceProvider的类型,那么SHA1就可以独立出来,就像System.Type.GetType("System.Security.Cryptography."+param+"CryptoServiceProvider"),param如果是SHA1,那么就是SHA1的Provider,如果是MD5,那么就是MD5的Provider。恩,先简单介绍到这里,具体的代码如下:

Posted in:
  • 网络编程与数据库
  • Windows编程技术
  • Web开发及相关
  • 系统应用程序开发
Tagged
  • asp.net
  • csharp
  • 反射
  • 哈希

IE6设置BackgroundImageCache背景图片缓存解决闪烁问题

今天在分析 拍拍网 页面时注意到下面这段脚本:

<!--[if IE 6]>
<script type="text/javascript">
// <![CDATA[
  document.execCommand("BackgroundImageCache", false, true);
// ]]>
</script>
<![endif]-->

当看到这段脚本时觉得非常好奇,这对于IE6做了什么限制?通过搜索知道,IE6默认不缓存背景图片,CSS每次更改图片的位置时都会重新发起图片请求,这样对于视觉上有一定的闪烁, 但是我过去的项目竟然感觉不到这样的问题,后来发现原来我一直用CSS Sprite解决这类加载问题的 (貌似CSS Sprite也会造成这种情况,难道是本地测试看不出来?)。看来今天又学到了一招,搞前端的也真不容易,尤其是那个让人无语的Internet Explorer 6。

下面再贴出一种不推荐的办法,那就是CSS里写入expression,为什么不推荐,主要是因为效率问题,CSS expression都会带来效率上的问题,所以要避免使用。

html {
  filter:expression(document.execCommand("BackgroundImageCache",false,true));
}

最后我把 拍拍网 上的那段代码结合网上的一些讲解改动如下:

<!--[if IE 6]>
<script type="text/javascript">
//<![CDATA[
try {
  document.execCommand("BackgroundImageCache", false, true);
} catch(e) {}
//]]>
</script>
<![endif]-->

END

Posted in:
  • 前端开发与用户体验
  • Web开发及相关
Tagged
  • Web缓存
  • 网站优化
  • ie浏览器

笔记本插入鼠标后禁用Synaptics触摸板

单位里的一台联想笔记本,外接的USB鼠标,由于需要打Word文稿,经常无意间碰到触摸板,给打字带来了很大的困扰,本来以为很简单的事情,结果折腾了很久。

首先,按Fn键无法禁用触摸板,其次是控制面板的鼠标里,Synaptics触控板那里没有指定的设备,观察了下系统,发现安装的是Ghost版的Windows XP,然后我就怀疑是不是没有安装官方驱动,登录到联想的官方网站,按照提示输入型号,下载驱动包,然后安装,安装完毕后发现问题依旧。

经过网上的一番搜索,终于功夫不负有心人,让我找到了可行的方案:

1.首先登录Synaptics官方网站的驱动下载页面下载最新驱动,网址是: http://www.synaptics.com/support/drivers

2.下载注册表补丁并导入, [下载地址1] 或者[download id="1124"]。下载完毕后依次导入1.reg,2.reg。

3.依次打开控制面板,点击鼠标图标,选择最后一个“装置设定值”选项卡,然后勾选“连接外部USB指向装置时禁用内部指向装置。”,最后确定保存,这样在插入USB鼠标时就会自动停用触摸板,如果你需要彻底禁用触摸板,可以选择装置列表里的SynapticsTouchPad,然后选择禁用即可。

Posted in:
  • 计算机应用及维护
  • Windows系统
Tagged
  • 笔记本
  • 触摸板

VB利用键盘勾子实现按键消息截获

好久不用VB写程序了,但是不得不承认VB的简单和高开发效率,这点比C/C++要好很多,尤其是一些开发周期短,实用性较强的软件。近期应单位要求,开发个××系统(名称保密),然后有个功能就是截获按键,实现特殊的按键热键的功能,首先想到的就是SetWindowsHookEx、CallNextHookEx 和UnhookWindowsHookEx,是的,想法很好,但是在实际运用时发现这几个C/C++下好用的函数老是容易导致VB崩溃,有时连IDE一起挂了,纠结了,因为这个系统最大的要求就是稳定,不能中途崩溃,为此我还特地建立了崩溃恢复机制,好了废话不说,这个问题总是要解决的,网上找到的一类代码比较混杂,大多是有问题的,最终我在vbaccelerator找到了个稳定可行的版本,那就是 《Win32 Hooks in VB - The vbAccelerator Hook Library》 这篇文章所介绍的Hook Library [下载地址] [源代码]

使用方法很简单,下载那个ActiveX DLL,然后VB引用,然后在窗体级代码中输入:

Implements IWindowsHook

Private Sub Form_Load()
   InstallHook Me, WH_JOURNALRECORD
End Sub

Private Sub Form_QueryUnload( _
      Cancel As Integer, UnloadMode As Integer)
   RemoveHook Me, WH_JOURNALRECORD
End Sub

Private Function IWindowsHook_HookProc( _
      ByVal eType As vbalWinHook.EHTHookTypeConstants, _
      ByVal nCode As Long, _
      ByVal wParam As Long, _
      ByVal lParam As Long, _
      bConsume As Boolean) As Long

   If (eType = WH_JOURNALRECORD) Then

      Dim cEvent As cJournallParam
      Set cEvent = JournalRecordlParam(lParam)

      ' cEvent now contains information about
      ' the Journal record message.

   End If

End Function

当然 《Using a Journal Record Hook to Capture Mouse and Key Events from any System Window》 给出了一个完整的示例,大家不妨参考一下。

后来发现一个问题,那就是Visual Basic的ListView控件老是接收到我们要处理的按键,原本是想要处理的按键被按键勾子截获后就被“吃掉”不再继续传递,但是即使将IWindowsHook_HookProc的bConsume设为True也无济于事,后来我想起了以前看到的一个简单的办法,那就是KeyPress,看下面的代码:

Private Sub ListView1_KeyPress(KeyAscii As Integer)
  ' 如果按下字母B,则“吃掉”这个按键
  If KeyAscii = vbKeyB Then KeyAscii = 0
End Sub

上述代码中,如果接收到字母则将KeyAscii置0,这样控件本身就不再处理这个按键了。

Posted in:
  • Windows编程技术
  • 系统应用程序开发
Tagged
  • vb
  • 键盘勾子

VBScript利用WMI改变默认打印机实现指定打印机打印

之前我有篇文章 《VBScript实现Word和Excel的打印》 介绍了VBScript或者VBA实现Word和Excel的打印,基本上可以了解,其打印所要调用的是PrintOut方法,但是实际操作后发现其调用的是预先设置的默认打印机,有没有一种办法指定某种特定打印机进行打印呢?

非常遗憾的是,我没能找到较好的办法去解决这个问题,当然如果你知道的话可以与大家分享一下。经过一番搜索,发现微软脚本专家的 《如何将文本文件打印到默认打印机之外的打印机?》 这篇文章提出了一个变通的办法,大家可以尝试一下,具体的做法就是,先将所指定的打印机设为默认打印机,然后调用比如PrintOut打印,打印结束后,再将设置改回。

具体的代码摘录如下:

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" &_
  strComputer & "\root\cimv2")

' 下面检索当前的默认打印机
Set colPrinters =  objWMIService.ExecQuery _
  ("Select * from Win32_Printer Where Default = TRUE")

' 将\变为转义\\
For Each objPrinter in colPrinters
  strOldDefault = objPrinter.Name
  strOldDefault = Replace(strOldDefault, "\", "\\")
Next

' 找到我们所指定的打印机
Set colPrinters =  objWMIService.ExecQuery _
  ("Select * from Win32_Printer Where " &_
  "Name = '\\\\atl-ps-01\\printer2'")

For Each objPrinter in colPrinters
  objPrinter.SetDefaultPrinter() ' 设为默认
Next

WScript.Sleep 2000

' 执行打印的操作
' .PrintOut

' 还原原先的默认打印机
Set colPrinters =  objWMIService.ExecQuery _
  ("Select * from Win32_Printer Where Name = '" &_
   strOldDefault & "'")

For Each objPrinter in colPrinters
  objPrinter.SetDefaultPrinter()
Next

上述代码不难理解,只是为什么要转义一次,主要是因为WMI查询必须考虑类JavaScript或者C语言那样的转义字符,脚本专家上这样解释的:

为什么呢?是这样,如果默认打印机恰好为网络打印机,它将具有类似下面的名称:\\atl-ps-01\printer1。这并没有什么问题,只是稍后我们需要在脚本的 WQL Where 子句中使用该打印机名称。由于 \ 为保留字符,因此我们必须通过使用两个 \ 字符来“转义”每个 \ 字符;换句话说,我们的打印机(用于 Where 子句)的名称必须为 \\\\atl-ps-01\\printer1。我们使用 VBScript 的 Replace 函数来用一对 \ 替换打印机名称中的每个 \。

END

Posted in:
  • VBScript/JavaScript/Python
  • 系统应用程序开发
Tagged
  • 文档打印
  • vbscript

Scripting.Dictionary字典对象按键名Key进行冒泡排序

最近加班比较多,代码写得有点乱,结果今天出现了个低级错误,原本想把Scripting.Dictionary对象的Item按照指定fnCompare函数作用的Key字段排序,原本以为很简单,于是就拿了个普通的冒泡排序就用了起来,结果问题就出现了,这里有问题的代码如下:

Option Explicit

Function fnCompare(key1, key2)
 If CInt(key1)>CInt(key2) Then
   fnCompare = 1
 ElseIf CInt(key1)<CInt(key2) Then
  fnCompare = -1
 Else
  fnCompare = 0
 End If
End Function

Function Sort(dict)
  Dim i,j, temp
  Dim keys,items

  For i = 0 To  dict.Count-1
    For j = i+1 To dict.Count - 1
	  keys = dict.Keys
	  items = dict.Items
      If fnCompare(keys(i), keys(j))>0 Then
        ' 交换Item项目
        temp = items(i)
        dict.Item(keys(i)) = items(j)
        dict.Item(keys(j)) = temp        
        ' 交换Key键名
        temp = keys(i)
        dict.Key(keys(i)) = keys(j)
        dict.Key(keys(j)) = temp
      End If
    Next
  Next
End Function

Sub VBMain()
  Dim dict
  Set dict = WSH.CreateObject("Scripting.Dictionary")
    dict.Add "2", "a"
    dict.Add "8", "b"
    dict.Add "1", "c"
    Sort dict
  Set dict = Nothing
End Sub

Call VBMain()

貌似这样看上去很正常,算法没有什么问题,交换Item后交换Key,貌似也没有问题,但是偏偏运行时出现了下面这个错误框。

Posted in:
  • 数据结构及算法理论
  • 计算机学习与研究
Tagged
  • dictionary字典
  • 排序算法

© Wang Ye / 王 晔. All rights reserved.