Excel·VBA螺旋数组函数

2023-11-16

数字1-12从左上角顺时针依次输出的即为螺旋数组,如下图
在这里插入图片描述

1,由外到内顺时针的螺旋数组

实现方法1

从左上角开始,每一层按顶行、右列、底行、左列顺序依次赋值

代码思路

以数字1-30为例
在这里插入图片描述
观察可知,每行依次填入该层列数-1个数字(上图黄色/绿色部分),同理每列依次填入该层行数-1个数字(上图无色部分)。在遍历每层时,顶行的行号和左列的列号等于层数,底行的行号和右列的列号随着层数的递增而递减,由此编写代码如下

螺旋数组函数代码

将一维数组转为二维螺旋数组也可输出由内到外逆时针的螺旋数组

Function spiral(ByVal arr, ByVal num_rows&, ByVal num_cols&)
    '将一维数组转为二维螺旋数组,num_rows返回行数num_cols返回列数,大于1(数组从1开始计数)
    '可输出由外到内顺时针,也可倒序输出由内到外逆时针
    Dim i&, n&, w&, max_num&, max_n&, last_row&, last_col&
    '转为从1开始计数,检查参数num_rows、num_cols
    If LBound(arr) = 0 Then arr = WorksheetFunction.Transpose(WorksheetFunction.Transpose(arr))
    If num_rows * num_cols <> UBound(arr) Then
        Debug.Print "参数错误": Exit Function
    Else
        max_num = UBound(arr): ReDim result(1 To num_rows, 1 To num_cols)
    End If
    '初始值,n当前写入层数,max_n最大层数
    n = 1: max_n = WorksheetFunction.RoundUp(WorksheetFunction.Min(Array(num_rows, num_cols)) / 2, 0)
    last_row = num_rows - n + 1: last_col = num_cols - n + 1
    Do
        For i = n To last_col - 1  '该层顶行
            w = w + 1: result(n, i) = arr(w)
        Next
        For i = n To last_row - 1  '该层右列
            w = w + 1: result(i, last_col) = arr(w)
        Next
        For i = last_col To n + 1 Step -1  '该层底行
            w = w + 1: result(last_row, i) = arr(w)
        Next
        For i = last_row To n + 1 Step -1  '该层左列
            w = w + 1: result(i, n) = arr(w)
        Next
        If n < max_n Then n = n + 1
        last_row = num_rows - n + 1: last_col = num_cols - n + 1  '更新值
        If n = max_n And n = last_row Then  '最后一行
            For i = n To last_col
                w = w + 1: result(n, i) = arr(w)
            Next
        ElseIf n = max_n And n = last_col Then  '最后一列
            For i = n To last_row
                w = w + 1: result(i, n) = arr(w)
            Next
        End If
    Loop Until w >= max_num
    spiral = result
End Function

举例

Sub 螺旋数组测试()
    Dim a&, n&, m&, i&
    a = 49: n = 7: m = 7: tm = Timer
    ReDim arr(1 To a)
    For i = 1 To a
        arr(i) = i
    Next
    brr = spiral(arr, n, m)
    [a1].Resize(UBound(brr), UBound(brr, 2)) = brr
    Debug.Print "用时:" & Format(Timer - tm, "0.00")  '耗时
End Sub

在这里插入图片描述
输出由内到外逆时针的螺旋数组,仅需将arr数组倒序后传递给spiral函数

Sub 螺旋数组测试()
    Dim a&, n&, m&, i&, j&
    a = 49: n = 7: m = 7: tm = Timer
    ReDim arr(1 To a)
    For i = a To 1 Step -1
        j = j + 1: arr(j) = i
    Next
    brr = spiral(arr, n, m)
    [a1].Resize(UBound(brr), UBound(brr, 2)) = brr
    Debug.Print "用时:" & Format(Timer - tm, "0.00")  '耗时
End Sub

在这里插入图片描述

已测试参数
在这里插入图片描述

实现方法2

从左上角开始,根据每一层待赋值的坐标变化规律进行赋值

代码思路

以数字1-30为例
在这里插入图片描述
观察可知,每行依次填入该层列数-1个数字(上图黄色/绿色部分),同理每列依次填入该层行数-1个数字(上图无色部分),每往内一层可用行列数比外层少2,如此依次填完所有数字。(其中29-30的行比上一行19-21的行仅减少1个,是因为最后一层填入剩余数字)
每一层中数组坐标,先向右再向下(递增),然后向左再向上(递减),递增递减的代码方式有2种写法,如下

螺旋数组函数代码

将一维数组转为二维螺旋数组:2种代码形式,效果一致;第2种代码先定义递增递减顺序的(step_arr),更易理解

'Function spiral(ByVal arr, ByVal num_rows&, ByVal num_cols&)
'    '将一维数组转为二维螺旋数组,num_rows返回行数num_cols返回列数,大于1(数组从1开始计数)
'    Dim r&, c&, w&, mode_row As Boolean, max_n&, max_r&, max_c&, step_n&, last_row&, x&
'    '转为从1开始计数,检查参数num_rows、num_cols
'    If LBound(arr) = 0 Then arr = WorksheetFunction.Transpose(WorksheetFunction.Transpose(arr))
'    If num_rows * num_cols <> UBound(arr) Then
'        Debug.Print "参数错误": Exit Function
'    Else
'        max_n = UBound(arr): ReDim result(1 To num_rows, 1 To num_cols)
'    End If
'    '初始值,先按行写入;max_r和max_c都为当前行列数-1
'    r = 0: c = 0: max_r = num_rows - 1: max_c = num_cols - 1: step_n = 1
'    mode_row = True: last_row = num_rows: x = 2  '最外层循环结束时的行号为2,次外层为3,以此类推
'    Do
'        If mode_row = True Then  '按行写入
'            r = r + step_n
'            If r = last_row And max_r > 0 Then step_n = -1 Else step_n = 1
'            If c > 0 Then c = c - step_n
'            For i = 1 To max_c
'                w = w + 1: c = c + step_n: result(r, c) = arr(w)
'            Next
'            mode_row = False
'        Else    '按列写入
'            If r = last_row Then step_n = -1 Else step_n = 1
'            c = c + step_n
'            If r > 0 Then r = r - step_n
'            For i = 1 To max_r
'                w = w + 1: r = r + step_n: result(r, c) = arr(w)
'            Next
'            mode_row = True
'            If r = x And step_n = -1 Then  '每层循环结束后,更新值
'                x = x + 1: max_r = max_r - 2: max_c = max_c - 2
'                step_n = 1: last_row = last_row - 1
'                If max_r > 0 And max_c > 0 Then
'                    r = r - 1: c = c + 1
'                ElseIf max_r = 0 And max_c >= 0 Then
'                    max_c = max_c + 1: mode_row = True: r = r - 1: c = c + 1
'                ElseIf max_c = 0 And max_r > 0 Then
'                    max_r = max_r + 1: mode_row = False
'                End If
'            End If
'        End If
'    Loop Until w >= max_n
'    spiral = result
'End Function

Function spiral(ByVal arr, ByVal num_rows&, ByVal num_cols&)
    '将一维数组转为二维螺旋数组,num_rows返回行数num_cols返回列数,大于1(数组从1开始计数)
    Dim r&, c&, w&, mode_row As Boolean, max_n&, max_r&, max_c&, step_n&, last_row&, x&, n&
    '转为从1开始计数,检查参数num_rows、num_cols
    If LBound(arr) = 0 Then arr = WorksheetFunction.Transpose(WorksheetFunction.Transpose(arr))
    If num_rows * num_cols <> UBound(arr) Then
        Debug.Print "参数错误": Exit Function
    Else
        max_n = UBound(arr): ReDim result(1 To num_rows, 1 To num_cols)
    End If
    '初始值,先按行写入;max_r和max_c都为当前行列数-1
    r = 0: c = 0: max_r = num_rows - 1: max_c = num_cols - 1: step_n = 1
    step_arr = Array(, 1, 1, -1, -1)
    mode_row = True: last_row = num_rows: x = 2  '最外层循环结束时的行号为2,次外层为3,以此类推
    Do
        If mode_row = True Then  '按行写入
            r = r + step_n: n = n + 1: step_n = step_arr(n)
            If c > 0 Then c = c - step_n
            For i = 1 To max_c
                w = w + 1: c = c + step_n: result(r, c) = arr(w)
            Next
            mode_row = False
        Else    '按列写入
            n = n + 1: step_n = step_arr(n): c = c + step_n
            If r > 0 Then r = r - step_n
            For i = 1 To max_r
                w = w + 1: r = r + step_n: result(r, c) = arr(w)
            Next
            mode_row = True
            If r = x And step_n = -1 Then  '每层循环结束后,更新值
                x = x + 1: max_r = max_r - 2: max_c = max_c - 2
                n = 0: step_n = 1: last_row = last_row - 1
                If max_r > 0 And max_c > 0 Then
                    r = r - 1: c = c + 1
                ElseIf max_r = 0 And max_c >= 0 Then  '都=0,即返回正方形奇数数组
                    max_c = max_c + 1: mode_row = True: r = r - 1: c = c + 1
                ElseIf max_c = 0 And max_r > 0 Then
                    max_r = max_r + 1: mode_row = False
                End If
            End If
        End If
    Loop Until w >= max_n
    spiral = result
End Function

测试结果与实现方法1一致

2,由外到内逆时针的螺旋数组

实现方法与上面的 实现方法1 一样
将一维数组转为二维螺旋数组也可输出由内到外顺时针的螺旋数组

Function spiral_0(ByVal arr, ByVal num_rows&, ByVal num_cols&)
    '将一维数组转为二维螺旋数组,num_rows返回行数num_cols返回列数,大于1(数组从1开始计数)
    '可输出由外到内逆时针,也可倒序输出由内到外顺时针
    Dim i&, n&, w&, max_num&, max_n&, last_row&, last_col&
    '转为从1开始计数,检查参数num_rows、num_cols
    If LBound(arr) = 0 Then arr = WorksheetFunction.Transpose(WorksheetFunction.Transpose(arr))
    If num_rows * num_cols <> UBound(arr) Then
        Debug.Print "参数错误": Exit Function
    Else
        max_num = UBound(arr): ReDim result(1 To num_rows, 1 To num_cols)
    End If
    '初始值,n当前写入层数,max_n最大层数
    n = 1: max_n = WorksheetFunction.RoundUp(WorksheetFunction.Min(Array(num_rows, num_cols)) / 2, 0)
    last_row = num_rows - n + 1: last_col = num_cols - n + 1
    Do
        For i = n To last_row - 1  '该层左列
            w = w + 1: result(i, n) = arr(w)
        Next
        For i = n To last_col - 1  '该层底行
            w = w + 1: result(last_row, i) = arr(w)
        Next
        For i = last_row To n + 1 Step -1  '该层右列
            w = w + 1: result(i, last_col) = arr(w)
        Next
        For i = last_col To n + 1 Step -1  '该层顶行
            w = w + 1: result(n, i) = arr(w)
        Next
        If n < max_n Then n = n + 1
        last_row = num_rows - n + 1: last_col = num_cols - n + 1  '更新值
        If n = max_n And n = last_row Then  '最后一行
            For i = n To last_col
                w = w + 1: result(n, i) = arr(w)
            Next
        ElseIf n = max_n And n = last_col Then  '最后一列
            For i = n To last_row
                w = w + 1: result(i, n) = arr(w)
            Next
        End If
    Loop Until w >= max_num
    spiral_0 = result
End Function

举例

与 实现方法1 类似,可输出由外到内逆时针,也可倒序输出由内到外顺时针
同类参数举例
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Excel·VBA螺旋数组函数 的相关文章

  • 根据当前工作簿中的匹配值编辑主工作簿中的单元格

    这里的目标是比较两个工作簿之间 A 列中的值 当前工作簿是 xlsm 目标工作簿是 xlsx 如果找到任何匹配项 匹配值同一行的 E 列中的值在目标工作簿中发生更改 在这种情况下 必须将工作簿分开 我决定通过选择当前工作簿 A2 中的第一个
  • 更改列标签?例如:将“A”列更改为“名称”列

    谁能告诉我如何更改列标签 例如 我想将列 A 更改为列 名称 Excel Excel 的版本是什么 一般来说 您无法更改列字母 它们是 Excel 系统的一部分 您可以使用工作表中的一行来输入您正在使用的表格的标题 表标题可以是描述性列名称
  • 从“查找”结果中出现“下标超出范围”错误

    我想在 Excel 工作表中查找一个字符串 Excel 单元格值是使用公式计算的 当我运行这段代码时 Set firstExcel CreateObject Excel application firstExcel Workbooks Op
  • VBA - HTML 抓取问题

    我正在尝试从网站上抓取拍卖数据https www rbauction com heavy equipment auctions https www rbauction com heavy equipment auctions 我当前的尝试是
  • 从网站上的表格中抓取数据,而无需搜索标签

    这是这个问题的延续使用 InStr 搜索引号 空格 冒号等 https stackoverflow com questions 52673819 using instr to search for quotes spaces colons
  • Countif 不适用于小时和/或日期

    您好 我有 3 列内的数据 A 目的地 例如洛杉矶 B 承运人 例如 Ups C 发货时间 预计 4 00 使用的时间是24小时时间 不含Am Pm 我需要进行计数才能知道在特定时间我们有多少批货物 尝试过 COUNTIF A1 A100
  • 在 MS Outlook 中,报告所有未收到回复的已发送邮件

    我每天都会发送大量电子邮件 但常常无法跟踪哪些邮件得到了实际回复 有没有办法使用 VBA 脚本查看上周发送的所有消息 并检查他们是否收到回复 具体来说 是一份已发送电子邮件的报告 这些电子邮件尚未从至少一个发送到的地址收到回复 我了解一点
  • MS Access 表单按钮,允许用户浏览/选择文件,然后将文件导入到表中

    在我的数据库中 我可以使用以下命令创建命令按钮导入文件 DoCmd TransferText acImportDelim 导入的原始数据 导入规范 导入的原始数据 D Users Denise Griffith Documents Grif
  • 运行代码(而不是查询)时如何在状态栏上显示进度

    我已经发布了有关在 MS Access 2010 中运行查询时更新状态栏的问题 请参阅在 MS Access 中运行一系列查询时如何在状态栏上显示进度 https stackoverflow com questions 27765376 h
  • xlwings: 删除一个列 | Excel 中的行

    如何删除 Excel 中的一行 wb xw Book Shipment xlsx wb sheets Page1 1 range 1 1 clear clear 用于删除内容 我想删除该行 我很惊讶 clear 函数有效 但 delete
  • 在 Excel 表格中选择多列的代码

    我是 Excel VBA 新手 我需要修改我的代码 以便我能够进一步进行 我想在 Excel 表格中选择多个表格列 这是我的代码 Dim ws As Worksheet Dim tbl As ListObject Set ws Sheets
  • 如何使用 Nodejs 创建 Excel 文件?

    我是一名 Nodejs 程序员 现在我有一个数据表 我想将其保存为 Excel 文件格式 我该怎么做呢 我找到了一些 Node 库 但其中大多数是 Excel 解析器而不是 Excel 编写器 我使用的是 Linux 服务器 因此需要一些可
  • 如何在 Excel 中对一组数据进行排序以匹配另一组数据?

    我有一个不按字母或数字顺序排列的数据列表 我想对同一日期的第二个列表进行排序以匹配第一个列表 我无法更改数据的顺序 我的目标是将第二组中的附加数据粘贴回第一个数据集中 DATA SET A DATA SET B 22350 BH160 10
  • 在合并的单元格中选择、插入照片并将其居中

    我是一名研发面包师 正在为我的团队制作食谱模板 模板中有照片 但我需要轻松地允许他们单击一个按钮 打开照片的文件选择器 然后将该照片放在合并的单元格中 我其实不太擅长做这个 Sub InsertPhotoMacro Dim photoNam
  • VBA 有没有办法了解未使用的变量?

    标准 VBA 编辑器中是否有工具 方法或设置来警告已被修改的变量Dim med 但没有被使用 MZ Tools http www mztools com index aspx将搜索您的代码并告诉您哪些内容未被使用 VBA的版本可以找到her
  • VBA 完成 Internet 表单

    我正在寻找将 Excel 中的值放入网页的代码 Sub FillInternetForm Dim IE As Object Set IE CreateObject InternetExplorer Application IE naviga
  • 如何等到 Excel 计算公式后再继续 win32com

    我有一个 win32com Python 脚本 它将多个 Excel 文件合并到电子表格中并将其另存为 PDF 现在的工作原理是输出几乎都是 NAME 因为文件是在计算 Excel 文件内容之前输出的 这可能需要一分钟 如何强制工作簿计算值
  • 使用 OpenPyXL 迭代工作表和单元格,并使用包含的字符串更新单元格[重复]

    这个问题在这里已经有答案了 我想使用 OpenPyXL 来搜索工作簿 但我遇到了一些问题 希望有人可以帮助解决 以下是一些障碍 待办事项 我的工作表和单元格数量未知 我想搜索工作簿并将工作表名称放入数组中 我想循环遍历每个数组项并搜索包含特
  • 我如何以更好的方式编码而不是像这样的VBA编码

    我正在 Excel 中创建一个仪表板 但是我想知道是否有比这更好的编码方式 我想对其进行模块化 而不是这样做以使其更加整洁 Private Sub Afford If af Value True Then af afr Value Shee
  • 检查未绑定控件是否具有值的正确方法

    简单场景 一个表单和一个文本框 未绑定 Text1 If lt gt Text1 Then MsgBox Not Empty End If 上面的代码有效 表达方式 lt gt Text1如果文本框包含字符 则计算结果为 True 无论文本

随机推荐

  • 数据库相关知识和进阶知识

    目录 MySQL与Orcale EXPLAIN介绍 EXPLAIN 可以分析慢查询原因 查看MySQL存储空间大小 MySQL事务锁不执行严格的校验
  • Retrofit实现文件上传和下载【二】

    概述 通过前一篇的博客介绍 我们已经对Retrofit的使用有了一个大概的了解 今天来讲讲利用Retrofit进行文件的上传和下载 文件上传 服务器使用的是SSH框架 因此这里是以struts2的方式来获取数据的 我这里定义了三个字段用来接
  • Java发送手机短信验证码

    本次使用的是阿里云的短信服务 1 添加短信签名 签名名称要用的 在阿里云产品中搜 短信服务 gt 免费开通 gt 国内消息 2 添加短信模板 模版CODE需要用的 就在添加签名的旁边 3 创建用户 用户令牌和密码需要用的 然后选择 开始使用
  • bug复刻,解决方案---在改变div层级关系时,导致传参失败

    问题描述 在优化页面时 为了实现网页顶部遮挡效果 内容滚动 顶部导航栏不随着一起滚动 并且覆盖 做法是将内容都放在一个div里面 为这个新的div设置样式 margin top width heigh等 网页效果的确实现了 但是出现的新的问
  • Chisel实验笔记(一)

    最近在学习Risc v 其中伯克利大学开源了一款兼容Risc v指令集的处理器Rocket 而Rocket处理器是采用Chisel编写的 所以要学习Chisel Chisel的简单介绍如下 Chisel Constructing Hardw
  • 基于Arduino的音乐动感节奏灯

    1 音乐动感节奏灯是个什么东西 前段时间听音乐觉得无聊 便想着音乐光听也没意思啊 能不能 看见 音乐呢 于是谷歌了一番 发现还真有人做了将音乐可视化的东西 那就是音乐节奏灯 说的简单点就是LED灯光颜色亮度等随着音乐的节奏而发生变化 看了下
  • 最新机器人工程专业毕设选题推荐

    文章目录 1前言 2 如何选题 3 机器人工程 毕设 选题推荐 4 最后 1前言 近期不少学弟学妹询问学长关于机器人工程专业工程专业相关的毕设选题 学长特意写下这篇文章以作回应 以下是学长亲手整理相关的毕业设计选题 都是经过学长精心审核的题
  • Python-声明变量

    Python如何声明变量 在 Python 中 定义变量非常简单 只需要为变量赋一个值即可自动创建该变量 并推断出变量的数据类型 变量名可以是任意字母 数字或下划线组成 但是不能以数字开头 例如 定义名为 name 的变量 并将字符串 To
  • event类型 php,深入解析PHP的Laravel框架中的event事件操作

    有时候当我们单纯的看 Laravel 手册的时候会有一些疑惑 比如说系统服务下的授权和事件 这些功能服务的应用场景是什么 其实如果没有经历过一定的开发经验有这些疑惑是很正常的事情 但是当我们在工作中多加思考会发现有时候这些服务其实我们一直都
  • 服务器的协议端口在哪里设置,服务器的远程端口号在哪里设置

    服务器的远程端口号在哪里设置 内容精选 换一换 Linux云服务器一般采用SSH连接方式 使用密钥对进行安全地无密码访问 但是SSH连接一般都是字符界面 有时我们需要使用图形界面进行一些复杂操作 本文以Ubuntu 18 04操作系统为例
  • 飞旭体质健康测试云平台学生体质测试管理系统

    飞旭体测数据管理云平台是由体测设备 微信小程序和云平台构成 用户通过设备测试后 数据传输至云端 由云平台对数据进行针对性的统计分析 平台功能包括管理员分级管理 学生体质测试 学生体质测试成绩查询 测试数据管理统计分析 数据上报管理等内容 具
  • 15 周带你学好大一C语言!最详细C语言学习路线

    要学习 C 语言的读者抓紧时间看一下 我按照C语言学习视频的目录整理了一条以 周为单位时间 的学习路线 希望在开学后能按照这个进度去学习一遍 有要学习 C 语言的读者也可以参照 可能有些知识学习起来比较困难 比如说二进制这种涉及到底层方面的
  • iperf linux移植

    参考链接 1 iperf的git地址 windows版下载地址 git clone https github com esnet iperf git 2 下载到ubuntu上 3 找到交叉工具包的位置 opt arm ca9 linux g
  • 绘制复杂的层次的原理图

    一 绘制总体的区域块模块 1 新建一个PCB项目 在new中的project选择PCB 2 在项目中新建一个sheet文件 schemetic 然后找到place中的sheet Symbol Actions 3 修改每一个绿块的名称和文件名
  • 阻止移动端 touchmove 与 scroll 事件冲突

    在移动端开发过程中 如果要实现一个元素或按钮的拖动定位 会出现很多坑 例如 元素上下移动过程中 会触发 body 的 scroll 事件 导致整体的位置偏移 这时就需要 阻止移动端 touchmove 与 scroll 事件冲突 一 解决思
  • 【致敬未来的攻城狮计划】--RA2E1 开发板测评(3)按键输入

    前言 1 首先感谢 李肯前辈的活动 从而申请到了RA2L1开发板的测评 2 本文主要介绍按键输入的内容 3 学习本文需要准备的前提 致敬未来的攻城狮计划 RA2E1 开发板测评 1 keil环境配置 致敬未来的攻城狮计划 RA2L1 开发板
  • 自助Linux之问题诊断工具strace

    引言 Oops 系统挂死了 Oops 程序崩溃了 Oops 命令执行报错 对于维护人员来说 这样的悲剧每天都在上演 理想情况下 系统或应用程序的错误日志提供了足够全面的信息 通过查看相关日志 维护人员就能很快地定位出问题发生的原因 但现实情
  • 去除li前面小点点

    li list style type none
  • 3. 性能测试之目标评估

    文章目录 前言 一 模型1 根据日活计算目标QPS 1 原则 2 事例 二 模型2 根据压测数据评估最大支撑并发 1 原则 2 事例 3 备注 三 模型3 根据压测数据评估服务器资源 1 策略 2 备注 四 模型4 评估用户并发或峰值并发
  • Excel·VBA螺旋数组函数

    目录 1 由外到内顺时针的螺旋数组 实现方法1 代码思路 螺旋数组函数代码 举例 实现方法2 代码思路 螺旋数组函数代码 2 由外到内逆时针的螺旋数组 举例 数字1 12从左上角顺时针依次输出的即为螺旋数组 如下图 1 由外到内顺时针的螺旋