Excel·VBA表格横向、纵向相互转换

在这里插入图片描述
如图:对图中区域 A1:M6 横向表格,转换成区域 A1:C20 纵向表格,即 B:M 列转换成每2列一组按行写入,并删除空行。同理,反向操作就是纵向表格转换成横向表格

目录

    • 横向转纵向
      • 实现方法1
        • 转换结果
      • 实现方法2
        • 转换结果
    • 纵向转横向
      • 转换结果

横向转纵向

实现方法1

本文图1中,按“交期和交货数量”每5行2列为一组,依次按行写入,即按“交期”顺序排列

Sub 表格横向转纵向1()
    '分段转换,转换列之前同名不连续;不使用动态获取每行最后一列是考虑到部分选中拆分
    Dim num_col&, title_row&, del_empty As Boolean, rng As Range, del_rng As Range
    Dim first_col&, resize_r&, resize_c&, keep_rng, arr, brr, b$, r&, i&, j&
'--------------------参数填写:num_col、title_row都为数字,选中后才可运行代码
    num_col = 2    '需要拆分的数据每行固定的列数
    title_row = 1  '表头行数
    del_empty = True  '是否删除空行
    If Selection.Count = 1 Then Debug.Print "未选中列,无法运行代码": Exit Sub
    Set rng = Intersect(ActiveSheet.UsedRange, Selection)  'intersect语句避免选择整列造成无用计算
    '选中区域开始列号,转换行数、列数
    first_col = rng.column: resize_r = rng.Rows.Count - title_row: resize_c = rng.Columns.Count
    If resize_c Mod num_col <> 0 Then Debug.Print "选中列数不可平分": Exit Sub
    
    With ActiveSheet
        keep_rng = .Cells(title_row + 1, 1).Resize(resize_r, first_col - 1)  '不变区域
        arr = .Cells(title_row + 1, first_col).Resize(resize_r, resize_c)    '转换区域
        r = title_row + 1  '写入行号
        For i = num_col + 1 To UBound(arr, 2) Step num_col
            r = r + resize_r: .Cells(r, 1).Resize(resize_r, first_col - 1) = keep_rng
            For j = 1 To num_col
                brr = Application.index(arr, , i + j - 1)  '按列拆分
                .Cells(r, first_col + j - 1).Resize(resize_r, 1) = brr
            Next
        Next
        If del_empty Then  '删除空行
            For i = title_row + 1 To r + resize_r
                brr = .Cells(i, first_col).Resize(1, num_col)
                b = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(brr)), "")
                If Len(b) = 0 Then
                    If del_rng Is Nothing Then
                        Set del_rng = .Rows(i)
                    Else
                        Set del_rng = Union(del_rng, .Rows(i))
                    End If
                End If
            Next
            If Not del_rng Is Nothing Then del_rng.Delete  '删除行
        End If
        .Cells(1, first_col + num_col).Resize(1, resize_c - num_col).EntireColumn.Delete  '删除选中列
    End With
End Sub

转换结果

本文图1(转换前不含7-20行),选中 B:M 列,运行代码得到如下图结果: D:M 列被删除
在这里插入图片描述

实现方法2

本文图1中,按“产品规格”每个产品后面6组“交期和交货数量”转换为每6行2列,依次按行写入,即按“产品”顺序排列

以下代码使用了数组行列数转换函数,调用了wraparr函数,代码详见《Excel·VBA单元格区域行列数转换函数》(如需使用代码需复制)

Sub 表格横向转纵向2()
    '按行转换,转换列之前同名连续;不使用动态获取每行最后一列是考虑到部分选中拆分
    Dim num_col&, title_row&, del_empty As Boolean, rng As Range, del_rng As Range
    Dim first_col&, last_row&, resize_r&, resize_c&, keep_rng, arr, brr, b$, r&, i&, j&
'--------------------参数填写:num_col、title_row都为数字,选中后才可运行代码
    num_col = 2    '需要拆分的数据每行固定的列数
    title_row = 1  '表头行数
    del_empty = True  '是否删除空行
    If Selection.Count = 1 Then Debug.Print "未选中列,无法运行代码": Exit Sub
    Set rng = Intersect(ActiveSheet.UsedRange, Selection)  'intersect语句避免选择整列造成无用计算
    '选中区域开始列号、结束行号,转换行数、列数
    first_col = rng.column: last_row = rng.Rows.Count
    resize_r = rng.Rows.Count - title_row: resize_c = rng.Columns.Count: r = resize_c / num_col
    If resize_c Mod num_col <> 0 Then Debug.Print "选中列数不可平分": Exit Sub
    
    With ActiveSheet
        For i = last_row To title_row + 1 Step -1  '倒序循环
            keep_rng = .Cells(i, 1).Resize(1, first_col - 1)  '不变区域
            arr = .Cells(i, first_col).Resize(1, resize_c)    '转换区域
            arr = wraparr(arr, "row", r)  '调用函数将arr转换为r行num_col的数组
            .Cells(i + 1, 1).Resize(r - 1, 1).EntireRow.Insert  '插入行
            .Cells(i, 1).Resize(r, first_col - 1) = keep_rng
            .Cells(i, first_col).Resize(r, num_col) = arr
        Next
        If del_empty Then  '删除空行
            j = (last_row - title_row) * r + title_row  '总行数
            For i = title_row + 1 To j
                brr = .Cells(i, first_col).Resize(1, num_col)
                b = Join(WorksheetFunction.Transpose(WorksheetFunction.Transpose(brr)), "")
                If Len(b) = 0 Then
                    If del_rng Is Nothing Then
                        Set del_rng = .Rows(i)
                    Else
                        Set del_rng = Union(del_rng, .Rows(i))
                    End If
                End If
            Next
            If Not del_rng Is Nothing Then del_rng.Delete  '删除行
        End If
        .Cells(1, first_col + num_col).Resize(1, resize_c - num_col).EntireColumn.Delete  '删除选中列
    End With
End Sub

转换结果

本文图1(转换前不含7-20行),选中 B:M 列,运行代码得到如下图结果: D:M 列被删除
在这里插入图片描述

纵向转横向

使用自定义函数转换,具体说明见注释(key_col(0)为开始列号,之前的都为字典键,之后的都为待转换数据)

Function 纵向转横向(ByVal data_arr, ByVal key_col)  '按非key_col列为键横向合并数组
    '转换函数,arr为待转换数组(从1开始计数二维数组),key_col为列号数组(从0开始计数一维数组)
    '返回结果,从1开始计数二维数组;key_col(0)为开始列号,key_col(1)为结束列号,键在开始列号之前
    Dim dict As Object, num_col&, delimiter$, i&, j&, r&, c&, k$, max_c&, rr&, cc&
    If Not IsArray(data_arr) Or Not IsArray(key_col) Then Debug.Print "错误!参数都为数组": Exit Function
    Set dict = CreateObject("scripting.dictionary")
    num_col = key_col(1) - key_col(0) + 1: delimiter = Chr(28)  '分隔符
    ReDim res(1 To UBound(data_arr), 1 To UBound(data_arr) * num_col)
    
    For i = LBound(data_arr) To UBound(data_arr)
        k = ""
        For j = 1 To key_col(0) - 1
            k = k & delimiter & data_arr(i, j)
        Next
        If Not dict.Exists(k) Then
            r = r + 1: dict(k) = Array(r, key_col(0))
            For j = 1 To key_col(0) - 1
                res(r, j) = data_arr(i, j)
            Next
        Else
            c = dict(k)(1) + num_col: dict(k) = Array(dict(k)(0), c)
            max_c = WorksheetFunction.Max(max_c, c)  '最大列数
        End If
        rr = dict(k)(0): cc = dict(k)(1) - 1
        For j = key_col(0) To key_col(1)
            cc = cc + 1: res(rr, cc) = data_arr(i, j)
        Next
    Next
    ReDim result(1 To r, 1 To max_c + num_col - 1)  '去除res数组多余部分
    For i = 1 To UBound(result)
        For j = 1 To UBound(result, 2)
            result(i, j) = res(i, j)
        Next
    Next
    纵向转横向 = result
End Function

转换结果

对“横向转纵向”无论是方法1还是方法2,生成的结果进行如下转换,生成的“纵向转横向”结果都一致,如下图

Sub 表格纵向转横向()
    Dim arr, brr
    arr = [a2:c20]: brr = 纵向转横向(arr, Array(2, 3))
    [d1].Resize(UBound(brr), UBound(brr, 2)) = brr
End Sub

在这里插入图片描述
多列键也可使用自定义函数转换,更具通用性

Sub 表格纵向转横向()
    Dim arr, brr
    arr = [a2:d20]: brr = 纵向转横向(arr, Array(3, 4))
    [f1].Resize(UBound(brr), UBound(brr, 2)) = brr
End Sub

在这里插入图片描述
附件:《Excel·VBA表格横向、纵向相互转换(附件)》

扩展阅读:
《excelhome-多列转3列》
《excel吧-3列转多列》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/61556.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ThreadLocal有内存泄漏问题吗

对于ThreadLocal的原理不了解或者连Java中的引用类型都不了解的可以看一下我的之前的一篇文章Java中的引用和ThreadLocal_鱼跃鹰飞的博客-CSDN博客 我这里也简单总结一下: 1. 每个Thread里都存储着一个成员变量&#xff0c;ThreadLocalMap 2. ThreadLocal本身不存储数据&…

Jenkins 自动化部署实例讲解,另附安装教程!

【2023】Jenkins入门与安装_jenkins最新版本_丶重明的博客-CSDN博客 也可以结合这个互补看 前言 你平常在做自己的项目时&#xff0c;是否有过部署项目太麻烦的想法&#xff1f;如果你是单体项目&#xff0c;可能没什么感触&#xff0c;但如果你是微服务项目&#xff0c;相…

Android的Handler消息通信详解

目录 背景 1. Handler基本使用 2. Handler的Looper源码分析 3. Handler的Message以及消息池、MessageQueue 4. Handler的Native实现 4.1 MessageQueue 4.2 Native结构体和类 4.2.1 Message结构体 4.2.2 消息处理类 4.2.3 回调类 4.2.5 ALooper类 5. 总结&…

【千题百解】华为机试题:求最小公倍数

“所有命运馈赠的礼物,都已在暗中标好了价格” 👨🏻‍💻作者:鳄鱼儿 🍀个人简介 👨🏻‍🎓计算机专业硕士研究生 🦨阿里云社区专家博主 🌙CSDN博客专家 & Java领域优质创作者 题目 解题 Java实现 注意a和b相乘时可能超过int最大值。 import java.uti

python调用pytorch的clip模型时报错

使用python调用pytorch中的clip模型时报错&#xff1a;AttributeError: partially initialized module ‘clip’ has no attribute ‘load’ (most likely due to a circular import) 目录 现象解决方案一、查看项目中是否有为clip名的文件二、查看clip是否安装成功 现象 clip…

命令模式(Command)

命令模式是一种行为设计模式&#xff0c;可将一个请求封装为一个对象&#xff0c;用不同的请求将方法参数化&#xff0c;从而实现延迟请求执行或将其放入队列中或记录请求日志&#xff0c;以及支持可撤销操作。其别名为动作(Action)模式或事务(Transaction)模式。 Command is …

Spring Cloud Eureka 和 zookeeper 的区别

CAP理论 在了解eureka和zookeeper区别之前&#xff0c;我们先来了解一下这个知识&#xff0c;cap理论。 1998年的加州大学的计算机科学家 Eric Brewer 提出&#xff0c;分布式有三个指标。Consistency&#xff0c;Availability&#xff0c;Partition tolerance。简称即为CAP。…

初识性能测试

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录 什么是性能测试&#xff1f;为什么要做性能测试&#xff1f;性能测试常见术语及性能测试衡量指标并发用户数响应时间/平均响应…

华为Mate30报名鸿蒙 HarmonyOS 4.0.0.108 系统更新

华为 Mate 30 系列于 2019 年 11 月 1 日上市&#xff0c;包括 Mate 30 4G / 5G、Mate 30 Pro 4G / 5G、保时捷设计版 Mate30 共五款机型。华为 Mate 30 系列 5G 版搭载麒麟 990 5G 处理器&#xff0c;同时支持 SA 及 NSA 5G 双模&#xff0c;适配三大运营商的 5G / 4G / 3G / …

Mac显示隐藏文件夹

1、设置隐藏文件可见 defaults write com.apple.finder AppleShowAllFiles TRUE 2、killall Finder killall Finder

opencv的Mask操作,选择图片中感兴趣的区域

最近做目标检测任务的时候&#xff0c;需要对固定区域的内容进行检测&#xff0c;要用到opencv的mask操作&#xff0c;选择图片固定的区域 代码 import cv2 import numpy as npimg cv2.imread(data/images/smoking.png)# 弹出一个框 让你选择ROI | x,y是左上角的坐标 x,y,w,…

岩土工程仪器多通道振弦传感器信号转换器应用于隧道安全监测

岩土工程仪器多通道振弦传感器信号转换器应用于隧道安全监测 多通道振弦传感器信号转换器VTI104_DIN 是轨道安装式振弦传感器信号转换器&#xff0c;可将振弦、温度传感器信号转换为 RS485 数字信号和模拟信号输出&#xff0c;方便的接入已有监测系统。 传感器状态 专用指示灯方…

8.15锁的优化

1.锁升级(锁膨胀) 无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁 偏向锁:不是真的加锁,而是做了一个标记,如果有别的线程来竞争才会真的加锁,如果没有别的线程竞争就不会加锁. 轻量级锁:一个线程占领锁资源后,另一个线程通过自旋的方式反复确认锁是否被是否(这个过程比较…

10 种网页抓取而不会被阻止的方法

一、说明 在数据爬取中&#xff0c;你的scraper又被挡住了吗&#xff1f;这很令人沮丧。但我们冷静下来&#xff0c;看看业内别人的说法&#xff0c;并将与您分享十种简单的解决方案来获取您想要的数据。 以下是尝试在不被阻止的情况下成功进行网络抓取的简短概述&#xff1a;…

Netty使用和常用组件辨析

Netty 使用和常用组件 简述 <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId <version>4.1.42.Final </version> <scope>compile</scope> </dependency> Netty 的优势 1 、 AP…

总结 IO、存储、硬盘、文件系统相关常识

目录 一、IO是什么&#xff1f; 二、存储 三、硬盘 四、文件系统 4.1 文件目录和组织方式 4.2 文化路径 4.3 文件类型 4.4 文件系统操作 一、IO是什么&#xff1f; IO是英文Input/Output的缩写&#xff0c;指输入/输出。在计算机科学中&#xff0c;IO通常指计算机与外部设备或…

Pytest简介及jenkins集成

一、pytest介绍 pytest介绍 - unittest\nose pytest&#xff1a;基于unittest之上的单元测试框架 自动发现测试模块和测试方法 断言使用assert表达式即可 可以设置测试会话级、模块级、类级、函数级的fixtures 数据准备 清理工作 unittest&#xff1a;setUp、teardown、…

Maven可选依赖和排除依赖简单使用

可选依赖 可选依赖指对外隐藏当前所依赖的资源 在maven_04_dao的pom.xml,在引入maven_03_pojo的时候&#xff0c;添加optional <dependency><groupId>com.rqz</groupId><artifactId>maven_03_pojo</artifactId><version>1.0-SNAPSHOT&…

Spring Boot + Vue3前后端分离实战wiki知识库系统十一--文档管理功能开发三

文档内容的显示&#xff1a; 在上一次https://www.cnblogs.com/webor2006/p/17510360.html文档管理模块还差文档的显示木有完成&#xff0c;所以接下来先将这块模块给收尾了。 增加单独获取内容的接口&#xff1a; 概述&#xff1a; 在前端页面文档查询时&#xff0c;只查询了文…

WMS仓库管理系统研发规划说明

01 产品背景 1.1 背景概述 aboss WMS东南亚仓库管理系统是一个基于BigSeller系统的使用基础上&#xff0c;加上多仓库的解决思路&#xff0c;解决入库业务、出库业务、仓库调拨、库存调拨和虚仓管理等功能&#xff0c;对批次管理、物料对应、库存盘点、质检管理、虚仓管理和即…