Excel里最右下角那个单元格,获后列你按Ctrl+End就能跳过去。取最但VBA里想拿到最后一列的列号列号,这事儿比想象中要绕。获后列很多人第一反应是取最写Cells(1, Columns.Count).End(xlToLeft).Column,这行代码确实能跑,列号但它有个前提——你的获后列数据得从第一行开始就是连续的。要是取最第一行恰好有个空单元格,结果直接偏到左边去,列号你拿着错的获后列数据去循环,后面全崩。取最
我见过一个做库存表的列号朋友,他的获后列表头第一行合并了A1到C1写“基本信息”,D1空着,取最E1才开始写“入库日期”。列号用上面那行代码,他拿到的最后一列是C,后面E列往右的数据全被忽略。他查了一下午没找出来,最后发现是合并单元格惹的祸。
更稳的写法:从整个工作表找
靠谱一点的做法是用UsedRange。这个属性返回的是工作表里真正被用过的区域,不管你有没有合并单元格、有没有空行空列。代码长这样:
Dim lastCol As Long lastCol = ActiveSheet.UsedRange.Columns.Count + ActiveSheet.UsedRange.Column - 1 注意后面那个+ UsedRange.Column - 1。UsedRange.Columns.Count只告诉你用了多少列,不告诉你从哪列开始。如果你的数据从C列开始,用了5列,Columns.Count给你5,但实际最后一列是G,列号是7。加上起始列偏移再减一,才能得到真实的列号。
这个写法有个小坑:UsedRange有时候会“虚胖”。比如你曾经在Z列输入过东西又删了,Excel可能还认为Z列被用过。这时候需要先执行一次ActiveSheet.UsedRange,让它自己重新计算一下。我一般会在取列号之前加一句Dim rng As Range: Set rng = ActiveSheet.UsedRange,强制刷新。
还有一种情况:数据从中间某行才开始
有的表第一行是标题,第二行是空行,第三行才是真正的数据。这时候从第一行往左找就彻底没戏。换个思路,从A列往下找,看哪一行有数据,再往右找:
Dim lastRow As Long Dim lastCol As Long lastRow = Cells(Rows.Count, 1).End(xlUp).Row lastCol = Cells(lastRow, Columns.Count).End(xlToLeft).Column 先定位到最后一行,再从那一行往左扫。这个方法对大部分常规表格都管用。但要是最后一行恰好是个合计行,只有A列和B列有内容,那最后一列又找错了。所以得根据你表格的实际结构来选方法,没有一招吃遍天的。
Find方法:最精确但稍慢
如果你追求绝对准确,可以用Find。从整个工作表里找最后一个非空单元格:
Dim lastCell As Range Set lastCell = Cells.Find(What:="*", _ After:=Cells(1, 1), _ LookIn:=xlFormulas, _ LookAt:=xlPart, _ SearchOrder:=xlByColumns, _ SearchDirection:=xlPrevious) If Not lastCell Is Nothing Then lastCol = lastCell.Column End If SearchDirection设成xlPrevious,SearchOrder设成xlByColumns,就是从右往左、从下往上找第一个非空单元格。这个方法的缺点是慢,数据量大的时候能感觉到卡顿。小表无所谓,几万行的表我一般不用Find。
实际项目里我怎么选
日常写宏,如果表格结构规整、第一行就是表头且没有合并单元格,我直接用Cells(1, Columns.Count).End(xlToLeft).Column,快且简单。表格结构不确定、有合并单元格、或者数据起始位置不固定,就上UsedRange。需要绝对精确且不在乎那零点几秒的性能损耗,才用Find。
还有个细节:Columns.Count在Excel 2007以后是16384,对应XFD列。如果你在写兼容.xls的代码,得注意老版本只有256列。不过现在基本没人用.xls了,这个问题可以忽略。
最后提一句,拿到列号之后别急着用数字去写循环。比如For i = 1 To lastCol,如果中间有空列,你的循环还是会跑到空列上去。列号只是告诉你边界在哪,具体怎么遍历,还得看你的数据长什么样。


相关文章




精彩导读
热门资讯
关注我们