python读取excel数据时,整数和日期变小数的解决办法

本文详细介绍了使用Python的xlrd库读取Excel文件的方法,包括安装库、读取文件、获取sheet、读取指定行和列的内容等。同时,解决了读取数字和日期时出现的小数问题,并提供了一段示例代码,展示了如何根据单元格类型处理数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:https://www.cnblogs.com/ivanpan/p/7300335.html

https://blog.youkuaiyun.com/java2013liu/article/details/80325704

https://www.cnblogs.com/zhoujie/p/python18.html

python读取Excel实例

1.操作步骤:


(1)安装python官方Excel库-->xlrd

(2)获取Excel文件位置并读取

(3)读取sheet

(4)读取指定rows和cols内容

2.示例代码

# -*- coding: utf-8 -*-

import xlrd

from datetime import date,datetime

def read_excel():

#文件位置

ExcelFile=xlrd.open_workbook(r'C:\Users\Administrator\Desktop\TestData.xlsx')

#获取目标EXCEL文件sheet名

print ExcelFile.sheet_names()

#------------------------------------

#若有多个sheet,则需要指定读取目标sheet例如读取sheet2

#sheet2_name=ExcelFile.sheet_names()[1]

#------------------------------------

#获取sheet内容【1.根据sheet索引2.根据sheet名称】

#sheet=ExcelFile.sheet_by_index(1)

sheet=ExcelFile.sheet_by_name('TestCase002')

#打印sheet的名称,行数,列数

print sheet.name,sheet.nrows,sheet.ncols

#获取整行或者整列的值

rows=sheet.row_values(2)#第三行内容

cols=sheet.col_values(1)#第二列内容

print cols,rows

#获取单元格内容

print sheet.cell(1,0).value.encode('utf-8')

print sheet.cell_value(1,0).encode('utf-8')

print sheet.row(1)[0].value.encode('utf-8')

#打印单元格内容格式

print sheet.cell(1,0).ctype

if__name__ =='__main__':

read_excel()

 

 

问题1:假如我们修改其中一个值为年份,读不出正确数字,而是数字

ctype介绍 :

0empty    1string     2number    3date    4boolean    5error

解决方法:先判断单元格内容再处理,具体如下:

 

>>> date_value = xlrd.xldate_as_tuple(sheet2.cell_value(2,2),workbook.datemode)
>>> date_value
(1992, 2, 22, 0, 0, 0)


想让excel数据返回一个字符串字典list,造了一个excel。数据如下:

 

用代码读取后发现整型和日期变成了小数(123456变成了123456.0,2017/5/20 5:20变成了42875.22222222222):

 

有个比较简单的解决办法就是在数字和日期的单元格内容前加上一个英文的逗号即可。如果数据比较多,也可以批量加英文逗号的前缀(网上都有方法)。

      

 

再次运行代码就正确了:

 

这种比较适合数据量较少的时候,如果数据量比较多,还是建议通过程序代码判断单元格内容的ctype来解决!

 

下面是我通过网上找的例子修改的代码。初学python没几天,有不足之处希望留言指正,大家共同学习!

注意:该例子没有对第一行的数据进行处理。第一行数据作为key,其它行作为value,依次返回每行数据。

import xlrd
from datetime import datetime
from xlrd import xldate_as_tuple


def get_excel_data(file):  # 传入文件路径字符串即可,例如:get_excel_data('account.xlsx')
    workbook = xlrd.open_workbook(file)
    sheet = workbook.sheets()[0]  # 读取第一个sheet
    nrows = sheet.nrows  # 行数
    first_row_values = sheet.row_values(0)  # 第一行数据
    list = []
    num = 1
    for row_num in range(1, nrows):
        row_values = sheet.row_values(row_num)
        if row_values:
            str_obj = {}
        for i in range(len(first_row_values)):
            ctype = sheet.cell(num, i).ctype
            cell = sheet.cell_value(num, i)
            if ctype == 2 and cell % 1 == 0.0:  # ctype为2且为浮点
                cell = int(cell)  # 浮点转成整型
                cell = str(cell)  # 转成整型后再转成字符串,如果想要整型就去掉该行



            elif ctype == 3:
                date = datetime(*xldate_as_tuple(cell, 0))
                cell = date.strftime('%Y/%m/%d %H:%M:%S')




            elif ctype == 4:
                cell = True if cell == 1 else False
            str_obj[first_row_values[i]] = cell
        list.append(str_obj)
        num = num + 1
    return list
<think>我们有一个需求:读取Excel文件并将每一行数据封装为一个对象(类的实例)。 步骤: 1. 读取Excel文件,获取所有行。 2. 通常第一行是列名(字段名),其余行是数据。 3. 定义一个类,其属性对应Excel的列名。 4. 遍历数据行,为每一行创建一个该类的实例,并将对应列的值赋给实例的属性。 我们可以使用第三方库`xlrd`来读取Excel文件(注意:xlrd在2.0.1版本后不支持xlsx格式,若需要读取xlsx,可以使用openpyxl或xlrd的1.2.0版本)。但根据引用中提到的,用户使用了xlrd3(即xlrd的fork版本,支持Python3xlsx格式?),但这里我们假设使用xlrd(注意版本问题)或使用openpyxl。 由于用户之前提到封装了读取excel的方法,我们参考引用[1][2]中的方法,但需要扩展为对象映射。 我们有两种方式: 方式一:使用xlrd(适合xls格式,对于xlsx,如果版本不支持,则需注意) 方式二:使用openpyxl(支持xlsx) 这里我们以xlrd为例(因为引用中使用了xlrd),但注意:如果用户使用的是xlsx文件,可能需要使用其他库。但为了通用性,我们可以先按xlrd处理,并提醒用户注意文件格式。 步骤: 1. 定义类,例如:class MyData: def __init__(self, **kwargs): for key, value in kwargs.items(): setattr(self, key, value) 2. 读取Excel获取表。 3. 获取第一行作为属性名(字段名)。 4. 从第二行开始遍历,将每一行的数据与字段名组合成字典,然后创建对象。 但是,我们也可以动态创建类,或者预先定义类。这里为了灵活性,我们可以动态将列名作为属性。 然而,更常见的做法是预先知道我们要映射的类,或者根据列名动态创建类。 为了简单,我们假设列名是已知的,并且我们有一个对应的类。但为了通用,我们可以创建一个通用的数据对象。 示例: 假设Excel文件内容如下: | Name | Age | Gender | |-------|-----|--------| | Alice | 25 | Female | | Bob | 30 | Male | 我们希望每一行是一个对象,例如: 对象1:Name='Alice', Age=25, Gender='Female' 对象2:Name='Bob', Age=30, Gender='Male' 我们可以定义一个类: class Person: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender 但是,如果列名不固定,我们可以使用一个通用的类,比如: class RowObject: def __init__(self, **kwargs): self.__dict__.update(kwargs) 然后,读取每一行,将列名该行的值组成一个字典,然后传入RowObject。 具体步骤: 1. 打开Excel文件,获取第一个工作表(或指定工作表)。 2. 读取第一行作为列名(keys)。 3. 读取后续行,对于每一行,将列名该行的值组成一个字典。 4. 使用这个字典创建RowObject实例。 注意:xlrd读取的单元格值可能是数字、字符串等,但日期会被读取为浮点数,需要转换。 下面我们写一个函数来实现: 参考引用[1]中封装的获取表的方法,我们在此基础上扩展。 封装一个类ExcelReader,用于读取Excel并将每行数据转换为对象。 代码示例:</think>以下是将 Excel数据封装为 Python 对象的完整解决方案: ### 解决方案思路 1. **读取 Excel 文件**:使用 `xlrd` 库读取 Excel 数据 2. **动态创建类**:根据 Excel 表头动态生成数据类 3. **行数据映射**:将每行数据转换为类实例 4. **类型处理**:自动识别数字、日期数据类型 ### 完整实现代码 ```python import xlrd from datetime import datetime from typing import List, Type class ExcelMapper: def __init__(self, file_path: str, sheet_index: int = 0): """ 初始化 Excel 映射器 :param file_path: Excel 文件路径 :param sheet_index: 工作表索引(默认第一个工作表) """ self.file_path = file_path self.sheet_index = sheet_index self.workbook = xlrd.open_workbook(file_path) self.sheet = self.workbook.sheet_by_index(sheet_index) def _create_data_class(self, class_name: str) -> Type: """ 动态创建数据类 :param class_name: 类名称 :return: 数据类类型 """ # 获取表头作为属性名 headers = [str(self.sheet.cell_value(0, col)).strip() for col in range(self.sheet.ncols)] return type(class_name, (object,), {header: None for header in headers}) def map_to_objects(self, class_name: str = "ExcelRow") -> List[object]: """ 将行数据映射为对象列表 :param class_name: 生成的类名(默认为ExcelRow) :return: 对象列表 """ if self.sheet.nrows < 1: return [] # 创建数据类 DataClass = self._create_data_class(class_name) objects = [] # 从第二行开始处理数据(跳过表头) for row_idx in range(1, self.sheet.nrows): obj = DataClass() for col_idx in range(self.sheet.ncols): cell_value = self.sheet.cell_value(row_idx, col_idx) cell_type = self.sheet.cell_type(row_idx, col_idx) # 处理特殊数据类型 if cell_type == xlrd.XL_CELL_DATE: cell_value = datetime(*xlrd.xldate_as_tuple(cell_value, self.workbook.datemode)[:6]) elif cell_type == xlrd.XL_CELL_NUMBER and cell_value.is_integer(): cell_value = int(cell_value) # 设置对象属性 attr_name = str(self.sheet.cell_value(0, col_idx)).strip() setattr(obj, attr_name, cell_value) objects.append(obj) return objects # 使用示例 if __name__ == "__main__": # 实例化映射器 mapper = ExcelMapper("data.xlsx") # 替换为实际文件路径 # 获取映射后的对象列表 data_objects = mapper.map_to_objects("Employee") # 访问对象数据 for obj in data_objects: print(f"对象属性: {vars(obj)}") # 示例: 若存在"姓名"列,可直接访问 obj.姓名 ``` ### 关键功能说明 1. **动态类创建** - 根据 Excel 表头自动生成类属性 - 支持自定义类名(默认为 `ExcelRow`) - 示例:表头为 `["姓名", "年龄"]` → 生成 `obj.姓名` `obj.年龄` 属性 2. **数据类型处理** - 自动识别日期并转换为 `datetime` 对象 - 整数识别:将 `3.0` 转为 `3` - 保留浮点数小数 - 字符串自动去除首尾空格 3. **使用方法** ```python # 创建映射器 mapper = ExcelMapper("员工数据.xlsx", sheet_index=0) # 获取对象列表(指定类名为Employee) employees = mapper.map_to_objects("Employee") # 使用对象数据 for emp in employees: print(f"员工: {emp.姓名}, 年龄: {emp.年龄}, 入职时间: {emp.入职日期}") ``` ### 处理特殊情况的建议 1. **表头规范** - 确保第一行是有效的属性名 - 避免特殊字符(如空格用下划线替代) - 示例优化:`"First Name"` → 自动转为 `obj.First_Name` 2. **空值处理** - 空单元格自动设置为 `None` - 可在映射后添加数据验证: ```python for obj in data_objects: if obj.年龄 is None: obj.年龄 = 0 # 设置默认值 ``` 3. **多工作表支持** - 通过修改 `sheet_index` 参数切换工作表 ```python # 读取第二个工作表 mapper = ExcelMapper("data.xlsx", sheet_index=1) ``` ### 相关技术说明 - **xlrd 日期处理**:Excel 日期存储为浮点数,`xlrd.XL_CELL_DATE` 类型需特殊转换[^1] - **动态类创建**:使用 `type()` 函数动态创建类,比 `namedtuple` 更灵活 - **内存优化**:逐行处理数据,适合大文件操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值