golang 读取csv文件到excel--推荐使用【不同实现方式】

news2024/11/25 10:35:35

 需求:把下面的csv文件,自动写入到excel模版中,

1.自动按照csv的行数,以日期时间名问sheet名成写入到excel表的sheet名称中

2.自动复制excel的第一个sheet的所有内容,同时用csv文件的内容填充特定区域内容

xy1.csv文件

日期	最高温度	最低温度	天气	风力风向	空气质量
2023-01-01 周日	4°	0°	多云~阴	东北风1级	256 重度
2023-01-02 周一	6°	-4°	多云~晴	东风1级	285 重度
2023-01-03 周二	7°	-3°	多云~阴	东北风1级	296 重度
2023-01-04 周三	6°	-2°	多云~阴	东风1级	361 严重
2023-01-05 周四	8°	-2°	多云~晴	东南风1级	368 严重
2023-01-06 周五	14°	-2°	晴	西南风2级	174 中度
2023-01-07 周六	14°	-2°	晴	东北风1级	163 中度
2023-01-08 周日	12°	-3°	晴	东风1级	224 重度

 xx.xlsx文件[模版文件],需要依托这个excel模版进行复制N个sheet表格,把上面的csv文件填充进去

=================

不同版本,不同方式测试,建议参看结构体方式

一、问题版本

解决的难题,

1.解决读取中文乱码的问题;

2.自动化事项

读取csv文件到excel文件中,批量自动化设置

待解决的问题,文件名称的时间与表里时间不一致的问题

package main

import (
	"bytes"
	"encoding/csv"
	"fmt"
	"github.com/xuri/excelize/v2"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"io/ioutil"
	"strings"
)

// 生成表格数据
func creatxlsx(lists [][]string) {

	//f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
	f, err := excelize.OpenFile("施工日志模版.xlsx")
	if err != nil {
		return
	}

	for num, item := range lists {
		year_xq := item[0]
		year_xq_slices := strings.Split(year_xq, " ")

		year := year_xq_slices[0]

		//需要把2016-4-23修改年的格式为 2016年4月23日

		year_lists := strings.Split(year, "-")
		newyea := year_lists[0]
		newmon := year_lists[1]
		newday := year_lists[2]

		newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)
		xq := year_xq_slices[1]
		//xq := year_xq_slices[1]
		//=====================================
		zg := item[1]
		zd := item[2]
		tq := item[3]
		fengli := item[4]

		//sheetname  201302
		//fmt.Println("year===>", year)
		index, err := f.NewSheet(year)
		if err != nil {
			fmt.Println(err)
			return
		}
		err = f.CopySheet(num, index)
		if err != nil {
			return
		}
		//获取每个单元表
		evesheet := f.GetSheetName(num)
		f.SetCellValue(evesheet, "I7", tq)
		f.SetCellValue(evesheet, "I8", fengli)
		f.SetCellValue(evesheet, "I9", zg)
		f.SetCellValue(evesheet, "I10", zd)

		//表格中  年的位置    星期的位置
		f.SetCellValue(evesheet, "P6", newyear_fomat)
		f.SetCellValue(evesheet, "X6", xq)

		//if err := f.SaveAs("Book1.xlsx"); err != nil {
		//	fmt.Println(err)
		//}

	}
	if err := f.SaveAs("Book1.xlsx"); err != nil {
		fmt.Println(err)
	}

}

func readcsvline2() [][]string {
	lists := make([][]string, 0)

	//file, err := os.Open("xy1.csv")
	file, err := ioutil.ReadFile("xy1.csv")
	if err != nil {
		fmt.Println(err)
	}
	//解决读取csv中文乱码的问题
	reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
	reader.FieldsPerRecord = -1
	// csvdata, err := reader.ReadAll()

	for {
		csvdata, err := reader.Read() // 按行读取数据,可控制读取部分

		if err != nil && err != io.EOF {
			fmt.Println("Error:", err)
			break
		}

		if err == io.EOF {
			break
		}
		lists = append(lists, csvdata)
		//fmt.Println(csvdata)
	}
	//去掉csv文件头的那行
	return lists[1:]

}

func main() {

	lists := readcsvline2()

	creatxlsx(lists)

}

代码与python项目相似:

https://ht666666.blog.csdn.net/article/details/130973792?spm=1001.2014.3001.5502


二、修正版本

修正版本:

下面的版本完全可以使用了

可以使用了 

package main

import (
	"bytes"
	"encoding/csv"
	"fmt"
	excelize "github.com/xuri/excelize/v2"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"io/ioutil"
	"strings"
)

// 生成表格数据
func creatxlsx(lists [][]string) {

	//f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
	f, err := excelize.OpenFile("施工日志魔板.xlsx")
	if err != nil {
		return
	}

	for num, item := range lists {
		year_xq := item[0]
		year_xq_slices := strings.Split(year_xq, " ")

		year := year_xq_slices[0]

		//需要把2016-4-23修改年的格式为 2016年4月23日

		year_lists := strings.Split(year, "-")
		newyea := year_lists[0]
		newmon := year_lists[1]
		newday := year_lists[2]

		newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)
		xq := year_xq_slices[1]
		//xq := year_xq_slices[1]
		//=====================================
		zg := item[1]
		zd := item[2]
		tq := item[3]
		fengli := item[4]

		//sheetname  201302
		//fmt.Println("year===>", year)
		index, err := f.NewSheet(year)
		if err != nil {
			fmt.Println(err)
			return
		}
		err = f.CopySheet(num, index)
		if err != nil {
			return
		}
		//获取每个单元表
		evesheet := f.GetSheetName(index)
		//evesheet := f.GetSheetName(num)   //错误的地方,应该是上面的index
		f.SetCellValue(evesheet, "I7", tq)
		f.SetCellValue(evesheet, "I8", fengli)
		f.SetCellValue(evesheet, "I9", zg)
		f.SetCellValue(evesheet, "I10", zd)

		//表格中  年的位置    星期的位置
		f.SetCellValue(evesheet, "P6", newyear_fomat)
		f.SetCellValue(evesheet, "X6", xq)

		//if err := f.SaveAs("Book1.xlsx"); err != nil {
		//	fmt.Println(err)
		//}

	}
	if err := f.SaveAs("Book1.xlsx"); err != nil {
		fmt.Println(err)
	}

}

func readcsvline2() [][]string {
	lists := make([][]string, 0)

	//file, err := os.Open("xy1.csv")
	file, err := ioutil.ReadFile("xy1.csv")
	if err != nil {
		fmt.Println(err)
	}
	//解决读取csv中文乱码的问题
	reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
	reader.FieldsPerRecord = -1
	// csvdata, err := reader.ReadAll()

	for {
		csvdata, err := reader.Read() // 按行读取数据,可控制读取部分

		if err != nil && err != io.EOF {
			fmt.Println("Error:", err)
			break
		}

		if err == io.EOF {
			break
		}
		lists = append(lists, csvdata)
		//fmt.Println(csvdata)
	}
	//去掉csv文件头的那行
	return lists[1:]

}

func main() {

	lists := readcsvline2()

	creatxlsx(lists)

}

修正的地方 :

三、优化版本【可以使用了--推荐】

package main

import (
	"bytes"
	"encoding/csv"
	"fmt"
	"github.com/xuri/excelize/v2"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"io/ioutil"
	"strings"
)

// 生成表格数据
func creatxlsx(lists [][]string) {

	//f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
	f, err := excelize.OpenFile("conf/施工日志模版.xlsx")
	if err != nil {
		return
	}

	for _, item := range lists {
		year_xq := item[0]
		year_xq_slices := strings.Split(year_xq, " ")

		//2016-4-23
		year := year_xq_slices[0]
		//  星期三
		xq := year_xq_slices[1]
		//==================================
		//需要把2016-4-23修改年的格式为 2016年4月23日

		year_lists := strings.Split(year, "-")
		newyea := year_lists[0]
		newmon := year_lists[1]
		newday := year_lists[2]

		newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)

		//xq := year_xq_slices[1]
		//=====================================
		//最高温度,最低温度,天气,风力
		zg := item[1]
		zd := item[2]
		tq := item[3]
		fengli := item[4]

		//sheetname  201302
		//fmt.Println("year===>", year)

		//创建sheet表的名称为 2016-4-23 的表名
		index, err := f.NewSheet(year)
		if err != nil {
			fmt.Println(err)
			return
		}
		//复制序列号 0 的索引[需要的模版]到新的索引的位置
		err = f.CopySheet(0, index)
		//err = f.CopySheet(num, index)
		if err != nil {
			return
		}
		//获取每个单元表,获取新建sheet表的index,在这里获取每个单元格的sheet
		evesheet := f.GetSheetName(index)

		//设置单元格的值

		f.SetCellValue(evesheet, "I7", tq)
		f.SetCellValue(evesheet, "I8", fengli)
		f.SetCellValue(evesheet, "I9", zg)
		f.SetCellValue(evesheet, "I10", zd)

		//表格中  年的位置    星期的位置
		f.SetCellValue(evesheet, "P6", newyear_fomat)
		f.SetCellValue(evesheet, "X6", xq)

		//if err := f.SaveAs("Book1.xlsx"); err != nil {
		//	fmt.Println(err)
		//}

	}
	if err := f.SaveAs("Book1.xlsx"); err != nil {
		fmt.Println(err)
	}
	fmt.Println("数据处理完毕。")

}

func readcsvline2(csvname string) [][]string {

	lists := make([][]string, 0)

	//file, err := os.Open("xy1.csv")
	//打开csv文件的内容
	file, err := ioutil.ReadFile(csvname)
	//file, err := ioutil.ReadFile("xy1.csv")
	if err != nil {
		fmt.Println(err)
	}
	//解决读取csv中文乱码的问题
	reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
	reader.FieldsPerRecord = -1
	// csvdata, err := reader.ReadAll()

	for {
		csvdata, err := reader.Read() // 按行读取数据,可控制读取部分

		if err != nil && err != io.EOF {
			fmt.Println("Error:", err)
			break
		}

		if err == io.EOF {
			break
		}
		lists = append(lists, csvdata)
		//fmt.Println(csvdata)
	}
	//去掉csv文件头的那行
	return lists[1:]

}

func main() {

	for {
		var csvname string
		fmt.Println("请输入城市的天气csv表名称[q :退出]:")
		fmt.Scan(&csvname)

		if !strings.HasSuffix(csvname, ".csv") {
			fmt.Println("输入文件后缀错误,必须是*.CSV文件")
			break
		}

		//判断输出的是Q 还是	q ,都是通过字符串转换后都是小写进行判断
		newcsvnamne := strings.ToLower(csvname)
		if newcsvnamne == "q" {
			break
		}
		lists := readcsvline2(csvname)

		creatxlsx(lists)

	}

}

四、针对上面的代码优化,采用结构体方式进行重构,代码大部分重写【结构体方式】

采用结构体方式:重构了一下代码;

package main

import (
	"bytes"
	"encoding/csv"
	"fmt"
	"github.com/xuri/excelize/v2"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"io/ioutil"
	"strings"
	"time"
)

// 定义读取的csv文件的字段信息
type Csvfield struct {
	Yead_week string
	Zg        string
	Zd        string
	Tq        string
	Fengli    string
	Zhiliang  string
}

// 生成表格数据,升级版本,对应readcsvline2Dic的未文件
func creatxlsxU1(lists []Csvfield) {

	//f, err := excelize.OpenFile("施工日志模版.xlsx", excelize.Options{Password: "password"})
	f, err := excelize.OpenFile("conf/施工日志模版.xlsx")
	if err != nil {
		return
	}

	for _, item := range lists {
		year_xq := item.Yead_week
		year_xq_slices := strings.Split(year_xq, " ")

		//2016-4-23
		year := year_xq_slices[0]
		//  星期三
		xq := year_xq_slices[1]
		//==================================
		//需要把2016-4-23修改年的格式为 2016年4月23日

		year_lists := strings.Split(year, "-")
		newyea := year_lists[0]
		newmon := year_lists[1]
		newday := year_lists[2]

		newyear_fomat := fmt.Sprintf("%s年%s月%s日", newyea, newmon, newday)

		//xq := year_xq_slices[1]
		//=====================================
		//最高温度,最低温度,天气,风力
		zg := item.Zg
		zd := item.Zd
		tq := item.Tq
		fengli := item.Fengli

		//sheetname  201302
		//fmt.Println("year===>", year)

		//创建sheet表的名称为 2016-4-23 的表名
		index, err := f.NewSheet(year)
		if err != nil {
			fmt.Println(err)
			return
		}
		//复制序列号 0 的索引[需要的模版]到新的索引的位置
		err = f.CopySheet(0, index)
		//err = f.CopySheet(num, index)
		if err != nil {
			return
		}
		//获取每个单元表,获取新建sheet表的index,在这里获取每个单元格的sheet
		evesheet := f.GetSheetName(index)

		//设置单元格的值

		f.SetCellValue(evesheet, "I7", tq)
		f.SetCellValue(evesheet, "I8", fengli)
		f.SetCellValue(evesheet, "I9", zg)
		f.SetCellValue(evesheet, "I10", zd)

		//表格中  年的位置    星期的位置
		f.SetCellValue(evesheet, "P6", newyear_fomat)
		f.SetCellValue(evesheet, "X6", xq)

	}

	//文件名的组成方式target_36.xlsx文件名
	inttime := time.Now().Second()
	timestr := fmt.Sprintf("%02d", inttime)
	saveExcelname := "target_" + timestr + ".xlsx"
	if err := f.SaveAs(saveExcelname); err != nil {
		fmt.Println(err)
	}
	fmt.Println("数据处理完毕。")

}

// 返回[]Csvfield   方式 ,升级版本,以结构体方式进行
func readcsvline2Dic(csvname string) []Csvfield {

	lists := make([]Csvfield, 0)

	//file, err := os.Open("xy1.csv")
	//打开csv文件的内容
	file, err := ioutil.ReadFile(csvname)
	//file, err := ioutil.ReadFile("xy1.csv")
	if err != nil {
		fmt.Println(err)
	}
	//解决读取csv中文乱码的问题
	reader := csv.NewReader(transform.NewReader(bytes.NewReader(file), simplifiedchinese.GBK.NewDecoder()))
	reader.FieldsPerRecord = -1
	// csvdata, err := reader.ReadAll()

	for {
		csvdata, err := reader.Read() // 按行读取数据,可控制读取部分

		if err != nil && err != io.EOF {
			fmt.Println("Error:", err)
			break
		}

		if err == io.EOF {
			break
		}

		//数据组装到结构体中
		stc1 := Csvfield{Yead_week: csvdata[0],
			Zg:       csvdata[1],
			Zd:       csvdata[2],
			Tq:       csvdata[3],
			Fengli:   csvdata[4],
			Zhiliang: csvdata[5],
		}

		lists = append(lists, stc1)
		//fmt.Println(csvdata)
	}
	//跳过csv首行  字段头部分
	return lists[1:]

}

// 测试代码
func creatxlsxU2(lists []Csvfield) {
	for i, item := range lists {
		//fmt.Println(i, "====>", item)xy5
		fmt.Printf("%T%T", i, item)

		fmt.Println(item.Yead_week)
	}
}

func main() {

	//struct版本---->新的内容
	for {
		var csvname string
		fmt.Println("请输入城市的天气csv表名称[q :退出]:")
		fmt.Scan(&csvname)

		if !strings.HasSuffix(csvname, ".csv") {
			fmt.Println("输入文件后缀错误,必须是*.CSV文件")
			break

		}

		//判断输出的是Q 还是	q ,都是通过字符串转换后都是小写进行判断
		newcsvnamne := strings.ToLower(csvname)
		if newcsvnamne == "q" {
			break
		}
		lists := readcsvline2Dic(csvname)

		//fmt.Println(lists)

		creatxlsxU1(lists)

	}

}

五、编译,参加我以前写的内容;

编译exe文件+图标的链接地址:

https://ht666666.blog.csdn.net/article/details/124512392

 重点关注 :

如果打包命令不成功,需要安装mingw-w64这个软件【绿色版本解压即可使用】,关注我我的上个编译图标的链接

1.下载地址

https://sourceforge.net/projects/mingw-w64/

2.编译命令:
 

windres -o readcsvtoxlsxv2.1.syso readcsvtoxlsxv2.1.rc

windres -o  这个就是编译命令;

后面的两个

readcsvtoxlsxv2.1.syso  需要生成的文件[readcsvtoxlsxv2.1---》修改为你的程序名称]

readcsvtoxlsxv2.1.rc  ;你的第一次生成的文件

总结:

编译的时候的文件名基本都是一样的  只是后缀不一样的!

编译局题目内容见

Go在Window平台下编译出来的exe如何添加一个图标--推荐使用_雨师@的博客-CSDN博客

https://ht666666.blog.csdn.net/article/details/124512392

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

动态组件:类组件

函数组件的缺点: 第1次渲染组件,把函数执行,产生一个私有的上下文: EC(V),把解析出来的props「含children」 传递进来「但是被冻结了」,对函数返回的JSX元素「virtualDOMJ进行渲染。当我们点击按钮的时候,…

信道容量详解

本专栏包含信息论与编码的核心知识,按知识点组织,可作为教学或学习的参考。markdown版本已归档至【Github仓库:https://github.com/timerring/information-theory 】或者公众号【AIShareLab】回复 信息论 获取。 文章目录 信道容量信道容量的…

Django--创建项目与app的初步认识

目前我是想学习Django来搭建一个网站,记录一下我学初学的过程与遇到的问题。 我直接使用pycharm来创建一个Django项目,就不用在终端输入命令行的方式创建虚拟环境。 在终端输入,python manage.py runserver,点击连接web页面进行测…

为什么说python里面函数参数的默认值最好不要使用可变类型

之前发布过Python中函数的介绍:Python中函数的介绍 ,今天来做一个小小的补充说明:为什么说python里面函数参数的默认值最好不要使用可变类型 Python中,函数参数的默认值是在函数定义时计算的,而不是在每次函数调用时计…

机器人与外星人的对话:中国传统哲学的精髓是什么?

一天,机器人Robot和外星人Vick相遇,他俩聊了很多,主要是关于中国传统哲学的,下面是他俩的对话记录。 R:很多人表示他们很痛苦,禅师说那是因为“无明”,外星人,你怎么看? …

【P58】JMeter 简单数据写入器(Simple Data Writer)

文章目录 一、简单数据写入器(Simple Data Writer)参数说明二、准备工作三、测试计划设计 一、简单数据写入器(Simple Data Writer)参数说明 可以将原始数据直接保存到文件 使用场景:一般与 HTML 报告配合使用 使用…

【Python文本处理】基于运动路线记录GPX的文件解析,及对经纬度坐标的数学模型运动速度求解

【Python文本处理】基于运动路线记录GPX的文件解析,及对经纬度坐标的数学模型运动速度求解 解析 GPX文件格式 GPX文件本身其实就是坐标、海拔、时间、心率等综合性的xml文件 如图: 海拔:ele 时间:time 心率:heartr…

【用pytorch进行LSTM模型的学习】

用pytorch进行LSTM模型的学习 LSTM模型用pytorch,采用LSTM对seaborn数据集做预测基本步骤数据的观察特殊数据处理数据归一化模型的构建与选择模型的保存 飞机航班流量预测示例 LSTM模型 LSTM模型长下面这样,主要用在时间序列的预测,具有比RN…

5Why分析法

5Why分析法 由丰田公司的大野耐一提出的对一个问题点连续以5个“为什么”来自问,以追究其根本原因的分析方法。 模型介绍 所谓5Why分析法,又称“5问法”,也就是对一个问题点连续以5个“为什么”来提问,以追究其根本原因。虽为5个…

代码随想录第53天

1.最长公共子序列: 红字的问题都是和最长重复子数组那题的代码进行比较的出来的 动规五部曲分析如下: 确定dp数组(dp table)以及下标的含义 dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串tex…

solidity之智能拍卖案例

文章目录 实现一个简易的拍卖状态变量定义和初始化竞拍功能结束竞拍代码 实现一个简易的拍卖 角色分析:4类角色(拍卖师actioneer,委托人seller,竞买人bidder,买受人buyer) 功能分析:拍卖的基本…

Shell脚本攻略:Linux防火墙(一)

目录 一、理论 1.安全技术 2.防火墙 3.通信五元素和四元素 4.总结 二、实验 1.iptables基本操作 2.扩展匹配 3. 自定义链接 一、理论 1.安全技术 (1)安全技术 ①入侵检测系统(Intrusion Detection Systems)&#xff1…

汽车电子AUTOSAR之BswM模块

目录 前言 正文 总体设计框架 模式仲裁过程 模式控制过程 模式仲裁 模式请求来源(ModeRequestPorts) 模式条件(ModeCondition) 逻辑表达式(LogicExpressions) 模式规则(ModeRules) 模式规则的初始化 模式控制 模式控制基本流程 模式行为 常用函数接口 前言 首先&…

Dependency not found解决方案(Springboot,绝对有效)

目录 问题描述解决方案systemPathmvn install 问题描述 今天在弄一个项目的依赖的时候,easyexcel 的依赖就是下载不了,虽然我的 Maven 配置没问题。 依赖:    Maven 配置:    我切换了几个版本,也无法从镜像下…

git diff去除^M的方法

一,简介 本文主要介绍在git修改的时候,修改文件后,git diff查看修改内容时,发现修改的地方每行结束的地方都会有“^M”,很影响查看。故今天分享一种去除“ ^M”显示的方法,供参考。 二,问题原…

案例29:基于Springboot医疗挂号系统开题报告设计

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

最新版本Portraiture4.1中文版ps磨皮滤镜插件安装包

在Portraiture有非常强大的手动功能,可以为用户进行手动调整照片中的皮肤区域以达到更加完美的效果,软件还支持同时导入上千张照片,用户可以通过自动识别照片中的人脸从而依照自己的风格进行批量处理十分的方便快捷。 最新版本Portraiture 4…

空气污染气象学期末复习笔记

空气污染气象学 (一)研究什么 运用气象学方法研究空气污染物自排放源进入大气层后的散布规律,核心是研究大气输送和扩散 (二)大气污染 大气污染是指由于人类活动或自然过程引起某种物质进入大气中,呈现出足…

Mysql数据库入门基础篇--mysql 多表查询

【Mysql数据库入门基础篇--mysql 多表查询 🔻一、mysql 多表查询1.1 🍃 7种sql joins 的实现1.2 🍃 错误写法---笛卡尔积错误1.3 🍃 正确的多表select写法 🔻二、内连接( inner) join🔻三、 外连接&#xf…

【LeetCode】23. 合并 K 个升序链表

23. 合并 K 个升序链表(困难) 方法一:顺序合并 思路 ListNode* mergeTwoLists(ListNode *a, ListNode *b) {if ((!a) || (!b)) return a ? a : b;ListNode head, *tail &head, *aPtr a, *bPtr b;while (aPtr && bPtr) {if (…