Context Menu

Context Menu:单击鼠标右键而产生的环境菜单,字面意思也叫做这个也有另外一个名字叫做Shortcut Menu,快捷菜单。两者其实是一回事。

 

顾名思义,这两个名字都表明了其特征:context 上下文依赖,shortcut便捷,单击鼠标右键就有的,如在excel中选中任意一个单元格,右击鼠标弹出的就是Context Menu(Shortcut Menu)

 

 

对于VBA而言,控制Context Menu的对象是CommandBar对象。大概是因为有了Ribbon之后,CommandBar对象的地位变得比较特殊,虽然Excel用户界面元素有:

  1. 工具栏toolbar
  2. 菜单栏 menu bar
  3. 上下文菜单Context Menu

    实际上,你最好只用CommandBar对象来自定义上下文菜单Context Menu,用CommandBar对象自定义工具栏toolbar和菜单栏 menu bar,Excel会拦截代码并忽略一些命令。

    一句话, 在Excel2007以上版本,我们只用CommandBar对象来自定义上下文菜单Context Menu。

     

    CommandBars 对象成员

    代表容器应用程序中命令栏的 CommandBar 对象的集合。

方法

 

名称

说明

Add

创建一个新的命令栏并将其添加到命令栏集合中。

CommitRenderingTransaction

提交呈现事务。返回 Nothing。

ExecuteMso

执行由 idMso 参数标识的控件。

FindControl

获取一个符合指定条件的 CommandBarControl 对象。

FindControls

获取符合指定条件的 CommandBarControls 集合。

GetEnabledMso

如果启用了 idMso 参数标识的控件,则返回 True。

GetImageMso

返回由 idMso 参数标识的控件图像(缩放到指定的宽度和高度尺寸)的 IPictureDisp 对象。

GetLabelMso

将 idMso 参数标识的控件的标签作为 String 类型的值返回。

GetPressedMso

返回一个值,该值指示是否已按下 idMso 参数标识的 toggleButton 控件。

GetScreentipMso

将 idMso 参数标识的控件的屏幕提示作为 String 类型的值返回。

GetSupertipMso

将 idMso 参数标识的控件的超级提示作为 String 类型的值返回。

GetVisibleMso

如果 idMso 参数标识的控件可见,则返回 True。

ReleaseFocus

释放所有命令栏的用户界面焦点。

属性

 

名称

说明

ActionControl

获取一个 CommandBarControl 对象,该对象的 OnAction 属性设置为当前正在运行的过程。只读。

ActiveMenuBar

获取一个 CommandBar 对象,该对象代表容器应用程序中的活动菜单栏。只读。

AdaptiveMenus

此属性可选中或取消选中指定 Microsoft Office 中菜单是完全显示还是按个性化方式显示的选项的复选框控件。可读写。

Application

获取一个 Application 对象,代表 CommandBars 对象的容器应用程序(可以使用 Automation 对象的此属性返回该对象的容器应用程序)。只读。

Count

获取宿主应用程序中的命令栏数量。只读。

Creator

获取一个 32 位整数,指示创建 CommandBars 对象时所使用的应用程序。只读。

DisableAskAQuestionDropdown

如果启用了”应答向导”下拉菜单,则为 True。可读写。

DisableCustomize

如果禁用了工具栏的自定义功能,则为 True。可读写。

DisplayFonts

如果在”字体”框中以实际字体显示字体名称,则为 True。可读写。

DisplayKeysInTooltips

如果每个命令栏控件的快捷键都显示在”工具提示”中,则为 True。可读写。

DisplayTooltips

如果只要用户将指针放在命令栏控件上方就显示”屏幕提示”,则为 True。可读写。

Item

获取 CommandBars 集合中的 CommandBar 对象。只读。

LargeButtons

如果显示的工具栏按钮比常规尺寸要大,则为 True。可读写。

MenuAnimationStyle

获取或设置一个代表命令栏的动画方式的 MsoMenuAnimation。可读写。

Parent

获取 CommandBars 对象的 Parent 对象。只读。

事件

 

名称

说明

OnUpdate

该事件发生于命令栏改变时。

 

 

CommandBar 对象成员

代表容器应用程序中的一个命令栏。CommandBar 对象是 CommandBars 集合的成员。

方法

 

名称

说明

Delete

从集合中删除 CommandBar 对象。

FindControl

获取一个符合指定条件的 CommandBarControl 对象。

Reset

将内置命令栏重置为其默认配置。

ShowPopup

将指定的命令栏作为快捷菜单,在指定坐标或当前光标位置显示。

属性

 

名称

说明

AdaptiveMenu

获取一个 Boolean 类型的值,该值指定命令栏是否应包含自适应菜单。可读写。

Application

获取一个 Application 对象,代表 CommandBar 对象的容器应用程序(可以使用 Automation 对象的此属性返回该对象的容器应用程序)。只读。

BuiltIn

如果指定的命令栏是容器应用程序的内置命令栏,则获取 True。如果是自定义命令栏,则返回 False。只读。

Context

获取或设置一个可确定命令栏保存位置的字符串。该字符串由应用程序定义和解释。可读写。

Controls

获取一个代表命令栏上的所有控件的 CommandBarControls 对象。只读。

Creator

获取一个 32 位整数,指示创建 CommandBar 对象时所使用的应用程序。只读。

Enabled

获取或设置用于指定是否启用了指定 CommandBar 的 Boolean 值。可读写。

Height

获取或设置 CommandBar 的高度。可读写。

Index

获取一个 Long 类型的值,该值代表集合中 CommandBar 对象的索引号。只读。

Left

设置或获取从对象左边缘算起 CommandBar 相对于屏幕的水平距离(以像素为单位)。可读写。

Name

获取内置的 CommandBar 对象的名称。只读。

NameLocal

获取以容器应用程序的语言版本显示的内置命令栏名称,或者返回或设置自定义命令栏的名称。可读写。

Parent

获取 CommandBar 对象的 Parent 对象。只读。

Position

获取或设置一个代表命令栏位置的 MsoBarPosition 常量。可读写。

Protection

获取或设置一个 MsoBarProtection 常量,代表防止用户对命令栏进行自定义的方式。可读写。

RowIndex

获取或设置一个命令栏相对于同一停靠区域中其他命令栏的停靠顺序。该属性值可以是大于零的整数,也可以是以下 MsoBarRow 常量之一:msoBarRowFirst 或 msoBarRowLast。可读写。

Top

设置或获取指定的命令栏顶边到屏幕顶边的距离。对于固定命令栏,此属性返回或设置从命令栏到停靠区域顶部的距离。可读写。

Type

获取命令栏的类型。只读。

Visible

获取或设置命令栏的 Visible 属性。如果命令栏可见,则为 True。可读写。

Width

获取或设置指定命令栏的宽度(以像素为单位)。可读写。

 

 

 

 

删除空行专题(第一版)

删除空行注定在Excel中是一个常见的话题,其实现方式多样,可谓五花八门。不过,我现在在复习《Excel 2010 Power Programming with VBA》一书中有非常通用的一段代码:

Sub DeleteEmptyRows()

Dim LastRow As Long

Dim r As Long

Dim Counter As Long

Application.ScreenUpdating = False

LastRow = ActiveSheet.UsedRange.Rows.Count + ActiveSheet.UsedRange.Rows(1).Row – 1

For r = LastRow To 1 Step -1

If Application.WorksheetFunction.CountA(Rows(r)) = 0 Then

Rows(r).Delete

Counter = Counter + 1

End If

Next r

Application.ScreenUpdating = False

MsgBox Counter & “empty rows were deleted”

End Sub

 

 

关于其他实现方法,等复习到其他VBA书籍再提。

例子文档

关于Inputbox

Inputbox 的知识点

  1. Excel中的Inputbox和VBA中的Inputbox的差异
  2. Excel 中的Inpubox 中的参数 Type:= 8
  3. Excel 中的Inpubox ,使用时确保没有关闭屏幕更新。否则不能选中工作表

Sub GetUserRange2()

Dim UserRange As Range

Application.ScreenUpdating = False

Set UserRange = Application.InputBox(Prompt:=”For test”, Title:=”Test”, _

Default:=ActiveCell.Address, Type:=8) ‘Range selection

 

Application.ScreenUpdating = True

End Sub

The Four Disguises of ()

Not only does the
empty list evaluate to false
, but it is the only false value
in Common Lisp. Any value not equivalent to an empty list will be considered a true

value. This explains why the expression ‘(1) in the earlier example was treated as true. However, there are some other expressions in Lisp that are disguises for

the one and only empty list:

 

 

 

CL-USER 4 : 1 >(eq ‘() nil)

T

 

CL-USER 5 : 1 > (eq ‘() ())

T

 

CL-USER 6 : 1 > (eq ‘() ‘nil)

T

 

CL-USER 7 : 1 > (if (= (+ 1 2) 3) ‘yup ‘nope)

YUP

 

CL-USER 8 : 1 > (if (= (+ 1 2) 4) ‘yup ‘nope)

NOPE

 

CL-USER 9 : 1 > (if ‘(1) ‘the-list-has-stuff-in-it ‘the-list-is-empty)

THE-LIST-HAS-STUFF-IN-IT

 

CL-USER 10 : 1 > (if ‘() ‘the-list-has-stuff-in-it ‘this-list-is-empty)

THIS-LIST-IS-EMPTY

 

CL-USER 11 : 1 > (if (oddp 5) ‘odd-number ‘even-number)

ODD-NUMBER

 

CL-USER 12 : 1 > (if (oddp 5) ‘odd-number (/ 1 0))

ODD-NUMBER

 

 

CL-USER 2 : 1 > (defvar *number-is-odd* nil)

*NUMBER-IS-ODD*

 

CL-USER 3 : 1 > (when (oddp 5) (setf *number-is-odd* t) ‘odd-number)

ODD-NUMBER

 

CL-USER 4 : 1 > *number-is-odd*

T

 

CL-USER 5 : 1 > (unless (oddp 4) (setf *number-is-odd* nil) ‘even-number)

EVEN-NUMBER

 

CL-USER 6 : 1 > *number-is-odd*

NIL

 

 

 

Chapter 4 Making decision with condition

The Symmetry of nil and ()

One thing is particularly striking when we look at how Lisp commands and data structures work: They are imbued with symmetry in every conceivable way. This symmetry can give your Lisp code a certain elegance that other languages cannot have, and Lisp’s simple syntax is an important factor in making this symmetry possible.

 

例子1:

CL-USER 1 > (if ‘() ‘I-am-true ‘I-am-false)

I-AM-FALSE

 

哈哈 ‘() 代表False,也就是”This example shows that when we pass the empty list () into an if form, it evaluates as a false value, whereas a list that contains an item evaluates as true.”

 

 

CL-USER 2 > (if ‘(1) ‘This-is-True ‘This-is-false)

THIS-IS-TRUE

 

‘(1) 当然代表真

 

 

CL-USER 3 > (if ‘(haha) ‘This-is-True ‘This-is-false)

THIS-IS-TRUE


 

 

 

例子2:递归调用

CL-USER 4 > (defun my-length (list) (if list (1+ (my-length (cdr list))) 0))

MY-LENGTH

 

CL-USER 5 > (my-length ‘(list with four symbols))

4

This function is written in classic Lisp style. It calls itself recursively as it chomps items off the front of the list. Calling yourself in this way is not only

allowed in Lisp, but is often strongly encouraged. Lists in Lisp are recursive (conses of conses of conses . . .), so the act of consuming a list maps naturally

onto functions that are recursive.

NOTE :Calling yourself recursively can sometimes make for slow code. In Chapter 14, we’ll rewrite the my-length function using a special, potentially faster, type of recursion.

 

 

(defun my-length (list)

(if list

(1+ (my-length (cdr list)))

0))

(my-length ‘(list with four symbols))

 

 

 

 

添加三块监视:

监视1:(1+ (my-length (cdr list))) 查看中间结果。

监视2:list 查看参数变化

监视3:(my-length (cdr list))

当然还可以添加监视:(cdr list)

 

 

Lisp 语言介绍-师出有名,战无不胜

 

LISP语言简介

LISP是一种计算机表处理语言,是函数型语言。它是LIST Processing的缩写,是研究人工智能的有力工具,由约翰•麦卡锡(John.McCarthy)在1960年左右创造的一种基于λ演算的函数式编程语言。

LISP最初是作为书写字符与表的递归函数的形式系统出现的,1958年由美国麻省理工学院(MIT)的AI小组提出,1960年由MIT的John.McCarthy教授(麦卡西教授,举世闻名的计算机科学家,图灵奖获得者,后为美国斯坦福大学教授)整理成统称为LISP1.0的形式发表,以后陆续出现的LISP1.5(1962年)、LISP1.6、MACLISP、INTERLISP,COMMONLISP,GCLISP,CCLISP等等变种。在众多不同版本的流行的LISP语言中,使用最广泛的是INTERLISP(XEROX公司开发),MACLISP(麻省理工学院开发)和COMMONLISP。LISP是继FORTRAN(FORTRAN是1954年提出,1956年开始使用)之后出现的第二个古老的(1958年提出,1960年开始使用)计算机高级语言,至今使用近五十年仍受重视,并为人工智能语言的发展作出了不可磨灭的贡献。由此可见,LISP是一门历史悠久,用途广泛,功能极强,生命力极强的人工智能程序设计语言。

Lisp 长久以来一直被视为伟大的编程语言之一。其漫长的发展过程(接近五十年)中引发的追随狂潮表明:这是一门非同凡响的语言。在 MIT,Lisp 在所有程序员的课程中占了举足轻重的地位。像 Paul Graham 那样的企业家们将 Lisp 卓越的生产力用作他们事业成功起步的推动力。但令其追随者懊恼万分的是,Lisp 从未成为主流编程语言。作为一名 Java™ 程序员,如果您花一点时间研究 Lisp 这座被人遗忘的黄金之城,就会发现许多能够改进编码方式的技术。

LISP语言的发展经历了几个时期:

1. 两年酝酿阶段(1956~1958),这个时期形成了Lisp的基本思想;

2. 实现与应用时期(1958~1962),这个时期的发展基本上是单线的;

3. “百家争鸣”时期(1962~1984),在这个时期LISP的发展呈现多样化,形成了许多LISP方言,支持LISP的机器也越来越多。不同的机构团体在开发LISP方言的时候,或多或少对LISP的发展做出了自己的贡献;

4. 标准化时期(1984至今),LISP语言的发展进入了标准化时代。1980年代,Guy L. Steele编写了Common Lisp试图进行标准化,这个标准被大多数解释器和编译器所接受。

Lisp语言具有其他高级语言不可比拟的特征。它具有坚固的理论基础,丰富的表达能力,较强的可塑性,也提供了操作系统的许多设施,如命令解释器、文件管理、多任务等。所有这些特征为符号计算和人工智能研究提供了一个方便的工具。

LISP有很多种方言,各个实现中的语言不完全一样。在Unix/Linux系统中,还有一种和Emacs一起的Emacs Lisp(而Emacs正是用Lisp作为扩展语言进行功能扩展的)非常流行,并建立了自己的标准。

LISP语言的主要现代版本包括Common LispScheme

(1927-2011)

 

参考资料:

http://www.unix-center.net/bbs/viewthread.php?tid=13253

http://zh.wikipedia.org/wiki/LISP

http://www.lisp.org/index.html

http://www.ibm.com/developerworks/cn/java/j-cb02067.html

 

 

扩展日期函数

我懒的重新打了,例子太多。还是贴下代码以备后用:

Function XDATE(y, m, d, Optional fmt As String) As String

If IsMissing(fmt) Then fmt = “Short Date”

XDATE = Format(DateSerial(y, m, d), fmt)

End Function

 

Function XDATEADD(xdate1, days, Optional fmt As String) As String

Dim TempDate As Date

If IsMissing(fmt) Then fmt = “Short Date”

xdate1 = RemoveDay(xdate1)

TempDate = DateValue(xdate1)

XDATEADD = Format(TempDate + days, fmt)

End Function

 

Function XDATEDIF(xdate1, xdate2) As Long

xdate1 = RemoveDay(xdate1)

xdate2 = RemoveDay(xdate2)

XDATEDIF = DateSerial(Year(xdate1), Month(xdate1), Day(xdate1)) – DateSerial(Year(xdate2), Month(xdate2), Day(xdate2))

End Function

 

Function XDATEYEARDIF(xdate1, xdate2) As Long

Dim YearDiff As Long

xdate1 = RemoveDay(xdate1)

xdate2 = RemoveDay(xdate2)

YearDiff = Year(xdate2) – Year(xdate1)

If DateSerial(Year(xdate1), Month(xdate2), Day(xdate2)) < CDate(xdate1) Then YearDiff = YearDiff – 1

XDATEYEARDIF = YearDiff

End Function

 

Function XDATEYEAR(xdate1)

xdate1 = RemoveDay(xdate1)

XDATEYEAR = Year(DateValue(xdate1))

End Function

 

Function XDATEMONTH(xdate1)

xdate1 = RemoveDay(xdate1)

XDATEMONTH = Month(DateValue(xdate1))

End Function

 

Function XDATEDAY(xdate1)

xdate1 = RemoveDay(xdate1)

XDATEDAY = Day(DateValue(xdate1))

End Function

 

Function XDATEDOW(xdate1)

xdate1 = RemoveDay(xdate1)

XDATEDOW = Weekday(xdate1)

End Function

 

Private Function RemoveDay(xdate1)

‘ Remove day of week from string

Dim i As Integer

Dim Temp As String

Temp = xdate1

For i = 0 To 6 ‘Unabbreviated day names

Temp = Application.Substitute(Temp, Format(DateSerial(1900, 1, 0), “dddd”), “”)

Next i

For i = 0 To 6 ‘Abbreviated day names

Temp = Application.Substitute(Temp, Format(DateSerial(1900, 1, 0), “ddd”), “”)

Next i

RemoveDay = Temp

End Function

 

Sub SetMacroOptions()

‘ Add descriptions, and put in the Date & Time function category

On Error Resume Next

With Application

.MacroOptions macro:=”XDATE”, Description:=”Returns a date for any year between 0100 and 9999. fmt is an optional date formatting string.”, Category:=2

.MacroOptions macro:=”XDATEADD”, Description:=”Returns a date, incremented by a specified number of days. fmt is an optional date formatting string.”, Category:=2

.MacroOptions macro:=”XDATEDIF”, Description:=”Returns the number of days between date1 and date2 (date1-date2).”, Category:=2

.MacroOptions macro:=”XDATEYEARDIF”, Description:=”Returns the number of full years between date1 and date2 (date1-date2). Useful for calculating ages.”

.MacroOptions macro:=”XDATEYEAR”, Description:=”Returns the year for a date.”

.MacroOptions macro:=”XDATEMONTH”, Description:=”Returns the month for a date.”

.MacroOptions macro:=”XDATEDAY”, Description:=”Returns the day for a date.”

.MacroOptions macro:=”XDATEDOW”, Description:=”Returns an integer corresponding to the weekday for a date (1=Sunday).”

End With

End Sub

使用MacroOptions方法给自编函数添加说明

 

 

 

 

 

代码:

Sub DescribeFunction()

Dim FunctionName As String

Dim FunctionDescription As String

Dim FunctionCategory As Long

‘Dim Arg1Desc As String, Arg2Desc As String

 

FunctionName = “ROWN”

FunctionDescription = “模拟Row函数返回行数”

FunctionCategory = 5

Application.MacroOptions Macro:=FunctionName, Description:=FunctionDescription, Category:=FunctionCategory

End Sub

使用Windows API

在使用Windows API 函数之前,必须在代码模块的顶部声明这个函数.如果代码模块是UserForm、Sheet或ThisWorkbook的代码模块,就必须用private关键字声明这个API函数

 

声明API函数:

在使用哪一个API函数

这个API函数位于哪个库

这个API函数的参数

 

Declare PtrSafe Function GetWindowsDirectoryA Lib “kernel32″ (ByVal lpBuffer As String, ByVal nSize As Long) As Long

Sub ShowWindowsDir()

Dim WinPath As String * 255

Dim WinDir As String

WinPath = Space(255)

WinDir = Left(WinPath, GetWindowsDirectoryA(WinPath, Len(WinPath)))

MsgBox WinDir, vbInformation, “Windows Directory”

End Sub

 

Function WindowsDir()

‘Return the Windows directory

Dim WinPath As String * 255

WinPath = Space(255)

WindowsDir = Left(WinPath, GetWindowsDirectoryA(WinPath, Len(WinPath)))

End Function

 

 

检测Shift

 

#If VBA7 And Win64 Then

Declare PtrSafe Function GetKeyState Lib “user32″ (ByVal nVirtKey As Long) As Integer

#Else

Declare Function GetKeyState Lib “user32″ (ByVal nVirtKey As Long) As Integer

#End If

 

‘ Constants for the keys of interest

Const VK_SHIFT As Integer = &H10

Const VK_CONTROL As Integer = &H11

Const VK_MENU As Integer = &H12 ‘Alt key

 

 

Sub DisplayKeyStatus()

Dim TabChar As String * 1

Dim CRChar As String * 1

Dim Shift As Boolean, Control As Boolean, Alt As Boolean

Dim Msg As String

 

TabChar = Chr(9)

CRChar = Chr(13)

 

‘ Use API calls to determine which keys are pressed

If GetKeyState(VK_SHIFT) < 0 Then Shift = True Else Shift = False

If GetKeyState(VK_CONTROL) < 0 Then Control = True Else Control = False

If GetKeyState(VK_MENU) < 0 Then Alt = True Else Alt = False

 

‘ Build the message

Msg = “Shift:” & TabChar & Shift & CRChar

Msg = Msg & “Control:” & TabChar & Control & CRChar

Msg = Msg & “Alt:” & TabChar & Alt & CRChar

 

‘ Display message box

MsgBox Msg, vbInformation, “Key Status”

End Sub

Function过程的参数

一个参数

一个参数以上

使用数组作为参数

可选参数

 

 

使用数组:

Function SumArray(List) As Double

Dim Item As Variant

SumArray = 0

For Each Item In List

If WorksheetFunction.IsNumber(Item) Then SumArray = SumArray + Item

Next Item

End Function

可选参数:

Function UserName(Optional UpperCase As Variant)

If IsMissing(UpperCase) Then UpperCase = False

UserName = Application.UserName

If UpperCase Then UserName = UCase(UserName)

End Function

 

 

Function Draw(Rng As Variant, Optional Recalc As Boolean = False)

‘ Chooses one cell at random from a range

 

‘ Make function volatile if Recalc is True

Application.Volatile Recalc

 

‘ Determine a random cell

Draw = Rng(Int((Rng.Count) * Rnd + 1))

End Function

 

关于IsMissing 函数的参数必须是Variant数据类型.