普通行列转换

/*
普通行列转换(2007-11-18于海南三亚)

假设有张学生成绩表(tb)如下:
Name Subject Result
张三 语文  74
张三 数学  83
张三 物理  93
李四 语文  74
李四 数学  84
李四 物理  94
*/

-------------------------------------------------------------------------
/*

想变成
姓名         语文        数学        物理         
---------- ----------- ----------- -----------
李四         74          84          94
张三         74          83          93
*/

create table tb
(
   Name   
varchar(10) ,
   Subject
varchar(10) ,
   Result 
int
)

insert into tb(Name , Subject , Result) values('张三' , '语文' , 74)
insert into tb(Name , Subject , Result) values('张三' , '数学' , 83)
insert into tb(Name , Subject , Result) values('张三' , '物理' , 93)
insert into tb(Name , Subject , Result) values('李四' , '语文' , 74)
insert into tb(Name , Subject , Result) values('李四' , '数学' , 84)
insert into tb(Name , Subject , Result) values('李四' , '物理' , 94)
go

--静态SQL,指subject只有语文、数学、物理这三门课程。
select name 姓名,
 
max(case subject when '语文' then result else 0 end) 语文,
 
max(case subject when '数学' then result else 0 end) 数学,
 
max(case subject when '物理' then result else 0 end) 物理
from tb
group by name
/*
姓名         语文        数学        物理         
---------- ----------- ----------- -----------
李四         74          84          94
张三         74          83          93
*/

--动态SQL,指subject不止语文、数学、物理这三门课程。
declare @sql varchar(8000)
set @sql = 'select Name as ' + '姓名'
select @sql = @sql + ' , max(case Subject when ''' + Subject + ''' then Result else 0 end) [' + Subject + ']'
from (select distinct Subject from tb) as a
set @sql = @sql + ' from tb group by name'
exec(@sql)
/*
姓名         数学        物理        语文         
---------- ----------- ----------- -----------
李四         84          94          74
张三         83          93          74
*/

-------------------------------------------------------------------
/*
加个平均分,总分
姓名         语文        数学        物理        平均分                总分         
---------- ----------- ----------- ----------- -------------------- -----------
李四         74          84          94          84.00                252
张三         74          83          93          83.33                250
*/

--静态SQL,指subject只有语文、数学、物理这三门课程。
select name 姓名,
 
max(case subject when '语文' then result else 0 end) 语文,
 
max(case subject when '数学' then result else 0 end) 数学,
 
max(case subject when '物理' then result else 0 end) 物理,
 
cast(avg(result*1.0) as decimal(18,2)) 平均分,
 
sum(result) 总分
from tb
group by name
/*
姓名         语文        数学        物理        平均分                总分         
---------- ----------- ----------- ----------- -------------------- -----------
李四         74          84          94          84.00                252
张三         74          83          93          83.33                250
*/

--动态SQL,指subject不止语文、数学、物理这三门课程。
declare @sql1 varchar(8000)
set @sql1 = 'select Name as ' + '姓名'
select @sql1 = @sql1 + ' , max(case Subject when ''' + Subject + ''' then Result else 0 end) [' + Subject + ']'
from (select distinct Subject from tb) as a
set @sql1 = @sql1 + ' , cast(avg(result*1.0) as decimal(18,2)) 平均分,sum(result) 总分 from tb group by name'
exec(@sql1)
/*
姓名         数学        物理        语文        平均分                总分         
---------- ----------- ----------- ----------- -------------------- -----------
李四         84          94          74          84.00                252
张三         83          93          74          83.33                250
*/

drop table tb   

---------------------------------------------------------
--
-------------------------------------------------------
/*

如果上述两表互相换一下:即

姓名 语文 数学 物理
张三 74  83  93
李四 74  84  94

想变成
Name       Subject Result     
---------- ------- -----------
李四         语文      74
李四         数学      84
李四         物理      94
张三         语文      74
张三         数学      83
张三         物理      93
*/

create table tb1
(
   姓名
varchar(10) ,
   语文
int ,
   数学
int ,
   物理
int
)

insert into tb1(姓名 , 语文 , 数学 , 物理) values('张三',74,83,93)
insert into tb1(姓名 , 语文 , 数学 , 物理) values('李四',74,84,94)

select * from
(
 
select 姓名 as Name , Subject = '语文' , Result = 语文 from tb1
 
union all
 
select 姓名 as Name , Subject = '数学' , Result = 数学 from tb1
 
union all
 
select 姓名 as Name , Subject = '物理' , Result = 物理 from tb1
) t
order by name , case Subject when '语文' then 1 when '数学' then 2 when '物理' then 3 when '总分' then 4 end

--------------------------------------------------------------------
/*
加个平均分,总分
Name       Subject     Result              
---------- -------    --------------------
李四         语文      74.00
李四         数学      84.00
李四         物理      94.00
李四         平均分    84.00
李四         总分      252.00
张三         语文      74.00
张三         数学      83.00
张三         物理      93.00
张三         平均分    83.33
张三         总分      250.00
*/

select * from
(
 
select 姓名 as Name , Subject = '语文' , Result = 语文 from tb1
 
union all
 
select 姓名 as Name , Subject = '数学' , Result = 数学 from tb1
 
union all
 
select 姓名 as Name , Subject = '物理' , Result = 物理 from tb1
 
union all
 
select 姓名 as Name , Subject = '平均分' , Result = cast((语文 + 数学 + 物理)*1.0/3 as decimal(18,2)) from tb1
 
union all
 
select 姓名 as Name , Subject = '总分' , Result = 语文 + 数学 + 物理 from tb1
) t
order by name , case Subject when '语文' then 1 when '数学' then 2 when '物理' then 3 when '平均分' then 4 when '总分' then 5 end

drop table tb1

<think>好的,我现在需要解决用户的问题:如何在Excel中获取当前单元格的行号和列号。用户之前询问了动态引用其他工作簿单元格的方法,现在向查询自身单元格的行列号,可能是在进一步优化之前的动态引用公,或者进行其他需要行列信息的操作。 首先,用户提到的引用[1]和[3]都提到了在自动计算中引用自身单元格的情况,虽然他们的问题是关于润乾报表和集智数据平台,但Excel中的处理可能有相似之处。用户之前的问题中使用了ROW()和COLUMN()函数,比如在INDIRECT函数中结合ADDRESS生成地址。因此,可能用户已经接触过这些函数,但需要明确如何单独获取行列号。 接下来,我需要确认Excel中获取行列号的常用方法。最直接的函数是ROW()和COLUMN(),当不带参数时,它们返回当前单元格的行号和列号。例如,在单元格A1中输入=ROW()会得到1,=COLUMN()会得到1(因为A是第一列)。但用户可能需要的是列字母,比如A,这时候需要用ADDRESS或者CHAR函数转换。 另外,用户可能遇到的情况包括:在公中引用其他单元格时动态获取当前行列,或者在VBA中需要获取当前单元格的信息。根据引用[2],用户对VBA也有一定了解,可能需要这方面的解答。 需要注意的潜在问题是,用户可能误用这些函数,比如在数组公中,或者在非单元格的上下文中使用。此外,当公被复制到其他单元格时,相对引用会导致结果变化,但用户可能需要绝对的行列号,这时候需要锁定单元格引用,比如使用ROW(A1)或者COLUMN(A1),但如果是当前单元格的话,直接用ROW()和COLUMN()即可。 用户还可能想知道如何将列号转换为字母,这在动态构建单元格地址时非常有用。例如,使用CHAR(COLUMN()+64)在列号小于等于26时有效,但超过的话需要更复杂的处理,比如用SUBSTITUTE(ADDRESS(1,COLUMN(),4),"1","")来获取字母列标。 最后,用户可能的应用场景包括动态引用、条件格、数据验证等需要当前行列信息的场合。需要确保提供的解决方案覆盖这些情况,并提示注意事项,比如循环引用的问题,或者在VBA中使用时的不同方法。</think>在Excel中获取当前单元格的行号和列号,可以通过以下三种方法实现: --- ### 方法1:使用基础函数直接获取 **行号获取**: ```excel =ROW() ``` **列号获取**: ```excel =COLUMN() ``` **列字母获取**(适用于动态地址拼接): ```excel =SUBSTITUTE(ADDRESS(1, COLUMN(), 4), "1", "") ``` #### 示例: | 单元格 | 公 | 结果 | |--------|-------------|-----------| | B3 | `=ROW()` | 3 | | D5 | `=COLUMN()` | 4 | | F2 | `=SUBSTITUTE(ADDRESS(1,COLUMN(),4),"1","")` | F | --- ### 方法2:通过VBA自定义获取 若需在**宏或用户自定义函数**中获取当前单元格信息: ```vba ' 获取活动单元格行号 Function GetRow() As Long GetRow = ActiveCell.Row End Function ' 获取活动单元格列字母 Function GetColumnLetter() As String GetColumnLetter = Split(ActiveCell.Address(False, False), "$")(0) End Function ``` **使用方法**: ```excel =GetRow() ' 返回当前选中单元格的行号 =GetColumnLetter() ' 返回列字母(如"A") ``` --- ### 方法3:动态引用场景中的嵌套应用 在需要**动态生成地址**时(如`INDIRECT`函数中),可结合`ROW()`/`COLUMN()`实现精准定位: ```excel =INDIRECT("A" & ROW()) ' 引用当前行的A列单元格 =INDIRECT(ADDRESS(ROW(), COLUMN()-1)) ' 引用左侧相邻单元格 ``` --- ### 应用场景对比 | 场景 | 推荐方法 | 注意事项 | |---------------------|----------------------|---------------------------| | 公中直接显示行列号 | 方法1(ROW/COLUMN) | 避免在易失性函数中过度使用 | | 动态构建单元格地址 | 方法3(ADDRESS嵌套)| 注意绝对/相对引用模 | | 自动化脚本需求 | 方法2(VBA) | 需启用宏安全性设置 | --- ### 常见问题解决 1. **循环引用警告** 若在单元格A1中输入`=ROW(A1)`,Excel会识别为普通;但若输入`=ROW()`则可能因依赖自身触发循环引用(仅在特定条件下)。 2. **列字母转换限制** - 直接转换仅支持列号≤26(A-Z),超出需用以下公: ```excel =SUBSTITUTE(ADDRESS(1, COLUMN(), 4), "1", "") ``` 3. **跨工作表引用** 若需引用其他工作表的当前行列,需明确指定工作表: ```excel =Sheet2!A1 + ROW() ' 组合其他工作表的引用与当前行号 ``` --- ### 性能优化建议 - 在大型数据模型中,优先使用`ROW()`/`COLUMN()`而非`INDIRECT`,后者因实时解析地址可能降低计算效率[^1]。 - VBA方案适用于复杂逻辑,但频繁调用`ActiveCell`可能影响响应速度,建议改用`Target.Row`事件驱动模。 --- ### 相关问题 1. 如何在条件格规则中引用当前单元格的行号? 2. Excel公如何实现相对列引用(如始终取左侧第三列的值)? 3. 使用VBA获取选中区域的行号范围时需要注意什么?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值