目录

前言 1.1

概述 1.2

处理csv 1.3

处理excel 1.4

openpyxl 1.4.1

常用功能点 1.4.1.1

封装成函数 1.4.1.2

举例 1.4.1.3

常见问题 1.4.1.4

xlrd和xlwt 1.4.2

常见问题 1.4.2.1

pandas 1.4.3

win32com.client 1.4.4

附录 1.5

参考资料 1.5.1

前言

Python表格处理：CSV和Excel

最新版本：v1.0

更新时间：20210413

简介

整理如何用Python进行表格处理，尤其是csv和excel文件的相关操作。先概述csv和Excel操作的相关的库有哪些以及各自大概特点；再去详细介绍，用自带的csv库去读取和创建保存csv文件，以及封装出常用函数；以及处理Excel的，好用的openpyxl库，其常用的功能点、部分常用功能已封装成独立函数、通过具体例子来说明如何使用、以及常见的一些问题；介绍了xlutils的xlrd和xlwt的下载和安装，基本的操作，比如新建excel文件、追加和写入新的数据等，以及常见问题及解决办法；概述了pandas的操作csv和excel的相关函数；介绍了用win32com.client去处理Excel的图表。

源码+浏览+下载

本书的各种源码、在线浏览地址、多种格式文件下载如下：

Gitbook源码

crifan/python_process_csv_excel: Python表格处理：CSV和Excel

如何使用此Gitbook源码去生成发布为电子书

详见：crifan/gitbook_template: demo how to use crifan gitbook template and demo

在线浏览

Python表格处理：CSV和Excel book.crifan.com

Python表格处理：CSV和Excel crifan.github.io

离线下载阅读

Python表格处理：CSV和Excel PDF

Python表格处理：CSV和Excel ePub

Python表格处理：CSV和Excel Mobi

版权说明

此电子书教程的全部内容，如无特别说明，均为本人原创和整理。其中部分内容参考自网络，均已备注了出处。如有发现侵犯您版权，请通过邮箱联系我 admin 艾特 crifan.com，我会尽快删除。谢谢合作。

鸣谢

感谢我的老婆陈雪的包容理解和悉心照料，才使得我crifan有更多精力去专注技术专研和整理归纳出这些电子书和技术教程，特此鸣谢。

更多其他电子书

本人crifan还写了其他100+本电子书教程，感兴趣可移步至：

crifan/crifan_ebook_readme: Crifan的电子书的使用说明

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:45:54

概述

概述

csv

Excel

用Python处理csv和Excel的常见库有：

csv库

Python内置库：csv

pandas

读：pandas.read_csv

写：pandas.DataFrame.to_csv

Excel库

读写文件的库

openpyxl

功能强大，支持设置背景色等样式的细节设置

支持新的（Excel 2010之后的）格式：.xlsx

xlutils：

概述

整合了xlrd和xlwt，额外加copy等辅助功能

只支持Excel旧格式：.xls

相关库

读：xlrd

写：xlwt

pandas

读：pandas.read_excel

写：pandas.DataFrame.to_excel

其他

xlsxwriter

An alternative package for writing data, formatting information and, in particular, charts in the Excel 2010 format (ie: .xlsx)

pyxlsb

This package allows you to read Excel files in the xlsb format.

pylightxl

This package allows you to read xlsx and xlsm files and write xlsx files.

自动化操作的库

说明：对于Excel文件的自动化操作 =对标旧的Excel（其实是Microsoft的Office的）VBA脚本 = 英文称:Excel add-ins

注意：需要系统中已安装Excel软件

库

PyXLL

概述

PyXLL is a commercial product that enables writing Excel add-ins in Python with no VBA. Python functions can be exposed as worksheet functions (UDFs), macros, menus and ribbon tool bars.

主页

https://www.pyxll.com/

xlwings

概述

xlwings is an open-source library to automate Excel with Python instead of VBA and works on Windows and macOS: you can call Python from Excel and vice versa and write UDFs in Python (Windows only). xlwings PRO is a commercial add-on with additional functionality.

主页

https://www.pyxll.com/

如何选择

根据不同情况，选择合适的解析csv和Excel的Python库

数据量不大的 + 简单的 csv文件：Python自带的csv库

数据量不大的 + Excel旧文件.xls + 操作不复杂：xlutils (xlrd+xlwt)

数据量不大的 + Excel新格式.xlsx + 操作复杂 + 能设置样式：openpyxl

数据量较大的csv或Excel，主要用于数据处理和计算的：pandas

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:38:45

处理csv

处理csv

已把csv处理相关代码，整理成独立函数。

最新代码详见：

https://github.com/crifan/crifanLibPython/blob/master/python3/crifanLib/crifanCsv.py

https://github.com/crifan/crifanLibPython/blob/master/crifanLib/demo/crifanCsvDemo.py

下面分别介绍：

python读取csv文件

核心代码loadCsvFromFile：

import codecs
import csv

with codecs.open(csvFilePath, "r", encoding="utf-8") as csvFp:
    csvReader = csv.reader(csvFp)
    csvHeaders = next(csvReader) # <class 'list'>: ['url', '品牌', '子品牌', '车型', '车系']
    for eachRowList in csvReader:
        print("eachRowList=%s" % eachRowList)
        # eachRowList=['https://car.autohome.com.cn/pic/series-s19501/3548.html#pvareaid=2042220', 'Elemental', 'Elemental', '2014款 基本型', 'Elemental RP1']

已封装成函数：

def loadCsvFromFile(csvFilePath, fileEncoding="utf-8", isReturnDictList=True):
    """read data from csv file

    Args:
        csvFilePath (str): full csv file path
        fileEncoding (str): file encoding, default to 'utf-8'
        isReturnDictList (bool): return data is row dict list or tuple(header list, row list list)
    Returns:
        isReturnDictList=True  -> csv row dict list
        isReturnDictList=False -> (csv header list, csv row data list)
    Raises:
    """
    csvDictList = []

    csvHeaderList = []
    csvRowListList = []

    with codecs.open(csvFilePath, "r", encoding=fileEncoding) as csvFp:
        csvReader = csv.reader(csvFp)
        csvHeaderList = next(csvReader)
        print("csvHeaderList=%s" % csvHeaderList)
        # <class 'list'>: ['url', '品牌', '子品牌', '车型', '车系']
        # ['appName', 'pkgName', 'authorName', 'categoryName', 'appDownCount', 'apkUrl', 'detailUrl', 'searchKeyword']
        for eachRowList in csvReader:
            # print("eachRowList=%s" % eachRowList)
            # eachRowList=['https://car.autohome.com.cn/pic/series-s19501/3548.html#pvareaid=2042220', 'Elemental', 'Elemental', '2014款 基本型', 'Elemental RP1']
            # eachRowList=['传奇世界手游', 'com.tencent.cqsj', '盛大游戏', '网络游戏', '2577672', 'https://imtt.dd.qq.com/16891/apk/6B6261E845EB53DF06F6DFBE884B61C8.apk?fsname=com.tencent.cqsj_3.6.1.20_3006.apk&csr=1bbd', 'https://sj.qq.com/myapp/detail.htm?apkName=com.tencent.cqsj', '传奇']
            csvRowListList.append(eachRowList)

    if isReturnDictList:
        for eachRowList in csvRowListList:
            curRowDict = {}
            for curIdx, curHeader in enumerate(csvHeaderList):
                curRowValue = eachRowList[curIdx]
                curRowDict[curHeader] = curRowValue

            csvDictList.append(curRowDict)

        return csvDictList
    else:
        return csvHeaderList, csvRowListList

调用：

resultRowDictList = loadCsvFromFile(InputYingYongBaoSearchResultFullPath)

新建=写入 csv文件

rowValueList = [mongoId, invalidReason.name, sentence]
with codecs.open(gCurInvalidSentenceFullFilename, "a", encoding="utf-8") as csvFp:
    csvListWriter = csv.writer(csvFp)
    csvListWriter.writerow(rowValueList)

或：用dict去保存值（需要指定header）

gInvalidSentenceCsvHeaders = [‘MongoID’, ‘Reason’, ‘Sentence’]

rowDict = {
    "MongoID": mongoId,
    # "Reason": str(invalidReason),
    "Reason": invalidReason.name,
    "Sentence": sentence
}

with codecs.open(gCurInvalidSentenceFullFilename, "a", encoding="utf-8") as csvFp:
    csvDictWriter = csv.DictWriter(csvFp, fieldnames=gInvalidSentenceCsvHeaders)
    csvDictWriter.writerow(rowDict)

效果：

saveToCsvByDictList和saveToCsvByHeaderAndList

后来已封装成独立函数

代码：

import codecs
import csv

def saveToCsvByDictList(csvDictList, outputFilePath):
    # generate csv headers from dict list
    firstItemDict = csvDictList[0]
    csvHeaders = list(firstItemDict.keys())
    with codecs.open(outputFilePath, "w", "UTF-8") as outCsvFp:
        csvDictWriter = csv.DictWriter(outCsvFp, fieldnames=csvHeaders)

        # write header by inner function from fieldnames
        csvDictWriter.writeheader()

        for eachRowDict in csvDictList:
            csvDictWriter.writerow(eachRowDict)

def saveToCsvByHeaderAndList(csvHeaderList, csvRowListList, outputFilePath):
    with codecs.open(outputFilePath, "w", "UTF-8") as outCsvFp:
        csvWriter = csv.writer(outCsvFp)

        # write header from list
        csvWriter.writerow(csvHeaderList)

        # type1: write each row
        # for eachRowList in csvRowListList:
        #   csvWriter.writerow(eachRowList)

        # type2: write all rows
        csvWriter.writerows(csvRowListList)

writeheader是后来新增的

writeheader()：是python 2.7和Python 3.2之后才新增的

当然也可以自己写：

dw.writerow( dict((f,f) for f in dr.fieldnames) )
output.writerow(dict(zip(dr.fieldnames, dr.fieldnames)))

其实官方库的内部也是类似的实现

header = dict(zip(self.fieldnames, self.fieldnames))
self.writerow(header)

调用举例：

文件：crifanLib/demo/crifanCsvDemo.py

OutputFilenameByHeaderAndList = "OutputDemoData_ByHeaderAndList.csv"
OutputFilenameByDictList = "OutputDemoData_ByDictList.csv"

OutputCsvHeader = ["单词", "重复频率", "来源列表"]

curFile = os.path.abspath(__file__)
curFolder = os.path.dirname(curFile)

DemoRowListList = [
  ["a", 0.5, ['NewConcept', 'FamilyAndFriends']],
  ["about", 0.75, ['NewConcept', 'YLE', 'EverybodyUp']],
  ["above", 0.5, ['NewConcept', 'YLE']],
  ["abroad", 0.25, ['NewConcept']]
]

DemoDictList = [
  {
    "单词": "a",
    "重复频率": 0.5,
    "来源列表": ['NewConcept', 'FamilyAndFriends'],
  },
  {
    "单词": "about",
    "重复频率": 0.75,
    "来源列表": ['NewConcept', 'YLE', 'EverybodyUp'],
  },
  {
    "单词": "above",
    "重复频率": 0.5,
    "来源列表": ['NewConcept', 'YLE'],
  },
  {
    "单词": "abroad",
    "重复频率": 0.25,
    "来源列表": ['NewConcept'],
  },
]

def demoCsvOutput():
  # Demo1: save by list of each row item list
  fullFilePathByHeaderAndList = os.path.join(curFolder, OutputFilenameByHeaderAndList)
  saveToCsvByHeaderAndList(OutputCsvHeader, DemoRowListList, fullFilePathByHeaderAndList)

  # Demo1: save by list of dict, not need assign header
  fullFilePathByDictList = os.path.join(curFolder, OutputFilenameByDictList)
  saveToCsvByDictList(DemoDictList, fullFilePathByDictList)

  """
  单词,重复频率,来源列表
  a,0.5,"['NewConcept', 'FamilyAndFriends']"
  about,0.75,"['NewConcept', 'YLE', 'EverybodyUp']"
  above,0.5,"['NewConcept', 'YLE']"
  abroad,0.25,['NewConcept']
  """

输出csv文件效果：

csv（作为表格文件的）预览效果：

Mac中自带的预览的csv的效果：

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:38:59

处理excel

处理excel

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:41:45

openpyxl

openpyxl

openpyxl

一句话描述：read/write Excel 2010 xlsx/xlsm files

文档

首页

https://openpyxl.readthedocs.io/en/stable/

入门

Manipulating a workbook in memory — openpyxl 2.5.3 documentation

http://openpyxl.readthedocs.io/en/stable/tutorial.html

API

说明：开发期间如果遇到一些对象，需要查询其属性、函数等细节，可以去参考这些API文档

API入口

openpyxl package — openpyxl 3.0.7 documentation

http://openpyxl.readthedocs.io/en/stable/api/openpyxl.html

核心的类(API)

最顶层的： openpyxl.workbook.workbook.Workbook = 对应excel文件

https://openpyxl.readthedocs.io/en/stable/api/openpyxl.workbook.workbook.html#openpyxl.workbook.workbook.Workbook

第二层的：openpyxl.worksheet.worksheet.Worksheet = 对应excel内单个的tab页

https://openpyxl.readthedocs.io/en/stable/api/openpyxl.worksheet.worksheet.html#openpyxl.worksheet.worksheet.Worksheet

最底层的： openpyxl.cell.cell.Cell = 对应单元格

https://openpyxl.readthedocs.io/en/stable/api/openpyxl.cell.cell.html#openpyxl.cell.cell.Cell

相关的：样式styles (颜色，对齐方式等等)

openpyxl.styles package — openpyxl 3.0.7 documentation

http://openpyxl.readthedocs.io/en/stable/api/openpyxl.styles.html

安装

pip3 install openpyxl

确认已安装成功

去python的shell中导入，没问题，且能输出版本信息，即说明安装没问题

➜  ~ python3
Python 3.6.1 (default, May  6 2017, 14:32:57)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.38)] on darwin
Type “help”, “copyright”, “credits” or “license” for more information.
>>> import openpyxl
>>> openpyxl.__version__
'2.4.7'
>>>

附带：安装日志

➜  ~ pip3 install openpyxl
Collecting openpyxl
  Downloading openpyxl-2.4.7.tar.gz (156kB)
    100% |████████████████████████████████| 163kB 64kB/s
Collecting jdcal (from openpyxl)
  Downloading jdcal-1.3.tar.gz
Collecting et_xmlfile (from openpyxl)
  Downloading et_xmlfile-1.0.1.tar.gz
Building wheels for collected packages: openpyxl, jdcal, et-xmlfile
  Running setup.py bdist_wheel for openpyxl … done
  Stored in directory: /Users/crifan/Library/Caches/pip/wheels/f5/c0/e2/7bd8f5f74f0c8ee97cd551409f8c8d8c388540248d32a28b99
  Running setup.py bdist_wheel for jdcal … done
  Stored in directory: /Users/crifan/Library/Caches/pip/wheels/0f/63/92/19ac65ed64189de4d662f269d39dd08a887258842ad2f29549
  Running setup.py bdist_wheel for et-xmlfile … done
  Stored in directory: /Users/crifan/Library/Caches/pip/wheels/99/f6/53/5e18f3ff4ce36c990fa90ebdf2b80cd9b44dc461f750a1a77c
Successfully built openpyxl jdcal et-xmlfile
Installing collected packages: jdcal, et-xmlfile, openpyxl
Successfully installed et-xmlfile-1.0.1 jdcal-1.3 openpyxl-2.4.7

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:45:21

常用功能点

常用功能点

此处整理出openpyxl中常用的功能点。

基本操作

读取excel文件

from openpyxl import Workbook, load_workbook

wb = load_workbook(ExcelFullFilename) # work book

获取workbook的sheet

获取sheet列表

  sheetNameList = wb.get_sheet_names()

获取某个sheet

  ws = wb["yourSheetName"] # work sheet

获取sheet中的cell

curCell = ws.cell(row=rowIdx, column=columnIdx)
curCellValue = curCell.value

常见操作

对每个row循环处理

之前去循环rows是用

ws.iter_rows("A1:L2")

这种写法现在已废弃，建议换成：

ws["A1:L2"]

且看了官网:

Manipulating a workbook in memory — openpyxl 2.5.3 documentation

发现其实两种写法都可以：

range string的写法：["XM:YN"]，其中X，Y是字母，M，N是数字

  cell_range = ws['A1':'C2']

ws调用iter_rows时，传递row和col的参数

  for row in ws.iter_rows(min_row=1, max_col=3, max_row=2):
      for cell in row:
          print(cell)

设置背景色

用openpyxl设置背景色，用start_color+end_color：

nameCell.fill = PatternFill(start_color="AACF91", end_color="AACF91", fill_type="solid")

效果：

不要用PatternFill的bgColor

如果用（看起来以为可以工作的）PatternFill的bgColor：

```python
nameCell.fill = PatternFill(bgColor=Color("AACF91"), fill_type="solid")
```

结果会导致黑色背景

如何查看颜色和RGB转换HEX值

对于上述颜色设置的值AACF91是如何得到的？

先去查看本身excel的背景色的RGB值：

此处背景色绿色的RGB值是：170，207，145

去把RGB转成HEX值：

hex color

即可得到HEX值：

RGB: 170，207，145 -> HEX: #AACF91

批量设置样式（背景色、对齐方式等）

背景：想要针对表头的所有的cell单元格（包括合并后的），批量去设置其样式

背景色：绿色

对齐方式

左右：水平居中对齐

上下：垂直居中对齐

代码：

每个单元格循环去设置

aligmentCenter = Alignment(horizontal='center', vertical='center')
commonBackgroundColorHex = "AACF91"
commonFill = PatternFill(start_color=commonBackgroundColorHex, end_color=commonBackgroundColorHex, fill_type="solid")
for eachCommonRow in ws.iter_rows("A1:L2"):
    logging.info("eachCommonRow=%s", eachCommonRow)
    for eachCellInRow in eachCommonRow:
        logging.info("eachCellInRow=%s", eachCellInRow)
        eachCellInRow.alignment = aligmentCenter
        eachCellInRow.fill = commonFill

效果

设置自适应列宽

背景：openpyxl可以新建excel，但是表头内容显示不全：

希望表头的宽度，像另外一个手动创建并设置后的，去自动适应宽度：

解决办法：

由于openpyxl的sheet中的column_dimensions的auto_size，bestFit，collapsed，都无法启到此处想要的效果：自动设置列宽

最后只能单独设置宽度：

nameCell = ws["A1"]
nameCell.value = "名称"
ws.merge_cells(‘A1:A2')
ws.column_dimensions["A"].width = 15

isSeriesCell = ws["D1"]
isSeriesCell.value = "是否是系列"
ws.merge_cells(‘D1:D2')
# ws.column_dimensions["D"].auto_size = True
# ws.column_dimensions["D"].bestFit = False
# ws.column_dimensions["D"].collapsed = True
ws.column_dimensions["D"].width = 10

fitAgeRangeCell = ws["L1"]
fitAgeRangeCell.value = "适用年龄层（年）"
ws.merge_cells(‘L1:L2')
# ws.column_dimensions["L"].auto_size = True
# ws.column_dimensions["L"].bestFit = True
# ws.column_dimensions["L"].collapsed = False
ws.column_dimensions["L"].width = 14
# ws["L3"].value = "很长的值很长的值很长的值测试列宽"

间接实现自动设置列宽的效果：

设置行高

背景：表头的部分内容由于行高太低而不显示了

解决办法：增加行高

代码：

ws.row_dimensions[1].height = 30
ws.row_dimensions[2].height = 20

效果：增加了行高，内容完全显示

设置单元格自动换行

背景：之前已设置了 列表宽度（间接实现宽度自适应）+ 行高，导致现在显示效果很不好，有些内容没法完全显示

希望cell单元格的内容的自动换行。

希望效果：想要实现，类似于手动设置的：设置单元格格式->对齐->文本控制->勾选：自动对齐

的效果：内容可以完全显示

代码：

# curCell.style.alignment.wrap_text = True #AttributeError: 'str' object has no attribute 'alignment'
curCell.alignment = Alignment(wrapText=True)

效果：很长的多行内容，可以根据宽度，自动换行，内容得以完全显示

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:39:43

封装成函数

封装成函数

目前已把openpyxl常用的功能，封装成独立函数了。

最新完整代码详见：

https://github.com/crifan/crifanLibPython/blob/master/python3/crifanLib/thirdParty/crifanOpenpyxl.py

下面贴出部分代码供参考：

获取合并后单元格的原始值：isInCellRange + getCellRangeValue + getRealCellValue

背景：

用代码自动去判断，对于合并后的单元格中的内容：

（之前调试时发现的）自动检测出来后，对于后续的，单元格值是空：

但是属于同一系列的话：

那么后续单元格的值，在代码赋值时，也使用前面的值。

换句话说：

被合并后的单元的值，默认是空的

但是希望获取到被合并之前的值，即此处的合并后的左上角的第一个单元格的值

看看openpyxl是否能检测出来excel的单元格，是否是被合并的，且知道，具体合并了多少行（多少列）

这样才有利于后续单元格值为空时，使用前面的同系列的值

代码：

from openpyxl import Workbook, load_workbook

def isInCellRange(cellToCheck, cellRange):
    """
    to check a cell whether in a cell range
    :param cellToCheck:
    :param cellRange:
    :return:
        True : if cell in range
        False: if cell not in range
    """
    # logging.debug("cellToCheck=[%d:%d]", cellToCheck.row, cellToCheck.col_idx)
    # logging.debug("cellRange: row=[%d:%d] col=[%d:%d]",
    #              cellRange.min_row, cellRange.max_row, cellRange.min_col, cellRange.max_col)
    if (cellToCheck.row &gt;= cellRange.min_row) and \
        (cellToCheck.row &lt;= cellRange.max_row) and \
        (cellToCheck.col_idx &gt;= cellRange.min_col) and \
        (cellToCheck.col_idx &lt;= cellRange.max_col):
        logging.info("cell[%d:%d] with in cell range: row=[%d:%d] col=[%d:%d]",
                     cellToCheck.row, cellToCheck.col_idx,
                     cellRange.min_row, cellRange.max_row, cellRange.min_col, cellRange.max_col)
        return True
    else:
        return False

def getCellRangeValue(cellRange):
    """
    get cell range value -&gt; the top left cell value
    :param cellRange:
    :return:
    """
    topLeftCell = ws.cell(row=cellRange.min_row, column=cellRange.min_col)
    topLeftCellValue = topLeftCell.value
    return topLeftCellValue

def getRealCellValue(ws, curCell):
    """
    for openpyxl, to get real value from row and column
    expecially for merged cell, will get its (same) value from top-left cell value

    :param row:
    :param column:
    :return:
    """

    realCellValue = curCell.value

    mergedCellsRangesList = ws.merged_cells.ranges
    # logging.info("mergedCellsRangesList=%s", mergedCellsRangesList)

    # Note:
    # to efficiency , we only check cell in range or not when its value is None
    # for all merged cell value is None
    if not realCellValue:
        for eachCellRange in mergedCellsRangesList:
            if isInCellRange(curCell, eachCellRange):
                cellRangeValue = getCellRangeValue(eachCellRange)
                realCellValue =  cellRangeValue
                break

    return realCellValue

# parse excel file
wb = load_workbook(ExcelFullFilename)
logging.info("wb=%s", wb)
# sheetNameList = wb.get_sheet_names()
# logging.info("sheetNameList=%s", sheetNameList)
ws = wb[StorybookSheetTitle]
logging.info("ws=%s", ws)

# process each row in excel
# for curRowNum in range(realContentRowStartNum, ws.max_row + 1):
for curRowNum, eachRow in enumerate(ws.iter_rows(min_row=realContentRowStartNum)):
    curRowNum += realContentRowStartNum
    logging.info("-"*30 + " row[%d] " + "-"*30, curRowNum)

    ...
    # authorColNumCellValue = ws.cell(row=curRowNum, column=AuthorColNum).value
    authorColNumCellValue = getRealCellValue(ws, eachRow[AuthorColNum - 1])
    logging.info("col[%d] authorColNumCellValue=%s", AuthorColNum, authorColNumCellValue)
    # contentAbstractColNumCellValue = ws.cell(row=curRowNum, column=ContentSimpleIntroColNum).value
    contentAbstractColNumCellValue = getRealCellValue(ws, eachRow[ContentSimpleIntroColNum - 1])
    logging.info("col[%d] contentAbstractColNumCellValue=%s", ContentSimpleIntroColNum, contentAbstractColNumCellValue)
    # publisherColNumCellValue = ws.cell(row=curRowNum, column=PublisherColNum).value
    publisherColNumCellValue = getRealCellValue(ws, eachRow[PublisherColNum - 1])
    logging.info("col[%d] publisherColNumCellValue=%s", PublisherColNum, publisherColNumCellValue)
    ...

可以检测到后续的，值是None的，处于被合并区域内的Cell单元格：

2018/04/04 02:50:22 LINE 246  INFO    cell[147:14] with in cell range: row=[146:163] col=[14:14]

对应着147行，14列的：

然后就可以通过：

getCellRangeValue去得到合并区域的值==合并区域的最左上角（top left）的那个单元格的值：

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:39:34

举例

举例

此处列出一些用openpyxl操作excel的实际的例子，供参考。

用openpyxl读取excel文件

对于excel文件：

代码：

from openpyxl import Workbook, load_workbook

StorybookSheetTitle = u"绘本"
EnglishStorybookRootPath = "/Users/crifan/dev/dev_root/xxx"
ExcelFilename = "xxx资源2018.3.28_forDebug.xlsx"
ExcelFullFilename = os.path.join(EnglishStorybookRootPath, ExcelFilename)
AudioFilePathPrefix = EnglishStorybookRootPath

# parse excel file
wb = load_workbook(ExcelFullFilename) # work book
logging.info("wb=%s", wb)
# sheetNameList = wb.get_sheet_names()
# logging.info("sheetNameList=%s", sheetNameList)
ws = wb[StorybookSheetTitle] # work sheet
logging.info("ws=%s", ws)

# process each row in excel
for curRowNum in range(realContentRowStartNum, ws.max_row + 1):
    logging.info("-"*30 + " row[%d] " + "-"*30, curRowNum)

    hasAudioFileColNumCellValue = ws.cell(row=curRowNum, column=HasAudioFileColNum).value
    logging.info("col[%d] hasAudioFileColNumCellValue=%s", HasAudioFileColNum, hasAudioFileColNumCellValue)
    audioFilePathColNumCellValue = ws.cell(row=curRowNum, column=AudioFilePathColNum).value
    logging.info("col[%d] audioFilePathColNumCellValue=%s", AudioFilePathColNum, audioFilePathColNumCellValue)

输出：

2018/03/30 02:55:02 LINE 104  INFO    wb=<openpyxl.workbook.workbook.Workbook object at 0x107855c50>
2018/03/30 02:55:02 LINE 108  INFO    ws=<Worksheet "\u7ed8\u672c">
2018/03/30 02:55:02 LINE 113  INFO    mongoClient=MongoClient(host=[‘localhost:27017’], document_class=dict, tz_aware=False, connect=True)
2018/03/30 02:55:02 LINE 117  INFO    gridfsDb=Database(MongoClient(host=[‘localhost:27017′], document_class=dict, tz_aware=False, connect=True), u’gridfs’)
2018/03/30 02:55:02 LINE 125  INFO    fsCollection=<gridfs.GridFS object at 0x107864b50>

2018/03/30 02:55:02 LINE 129  INFO    —————————— row[3] ——————————
2018/03/30 02:55:02 LINE 132  INFO    col[12] hasAudioFileColNumCellValue=有
2018/03/30 02:55:02 LINE 134  INFO    col[13] audioFilePathColNumCellValue=None

（用PyCharm）调试输出的效果：

新建excel文件并保存数据和设置单元格样式

背景：希望新建这种效果的excel

并且创建对应的第一行和第二行的表头，且部分单元格是合并的

然后再一点点把之前已有的excel中的内容：

保存进来。

代码：

from openpyxl import Workbook, load_workbook
from openpyxl.styles import Alignment
from openpyxl.styles import PatternFill, colors, Color
from openpyxl.styles import NamedStyle, Font, Border, Side

# create new output unified format excel file
wbOut = Workbook()
logging.info("wbOut=%s", wbOut)
# wsStorybook = wbOut.create_sheet(StorybookSheetTitle)
wsStorybook = wbOut.active
wsStorybook.title = StorybookSheetTitle
wsSong = wbOut.create_sheet(SongSheetTitle)
logging.info("wsStorybook=%s, wsSong=%s", wsStorybook, wsSong)

# common style
alignmentCenter = Alignment(horizontal='center', vertical='center')
fontYahei12 = Font(name=u'微软雅黑', bold=True, size=12)
thinSide = Side(style='thin', color=colors.BLACK)
allBlackThinBorder = Border(left=thinSide, top=thinSide, right=thinSide, bottom=thinSide)

# several type of headers style
NamedStyleCommonHeader      = "CommonHeader"
NamedStyleStorybookHeader   = "StorybookHeader"
NamedStyleSongHeader        = "SongHeader"
NamedStyleFileHeader        = "FileHeader"

commonBkgColorHex = "AACF91"
commonFill = PatternFill(start_color=commonBkgColorHex, end_color=commonBkgColorHex, fill_type="solid")

...

commonStyleHeader = NamedStyle(name=NamedStyleCommonHeader)
commonStyleHeader.font = fontYahei12
commonStyleHeader.border = allBlackThinBorder
commonStyleHeader.alignment = alignmentCenter
commonStyleHeader.fill = commonFill
wbOut.add_named_style(commonStyleHeader)

...

# init headers
def initOutputExcelHeaders(ws):
    logging.info("ws=%s", ws)

    nameCell = ws["A1"]
    nameCell.value = "名称"
    ws.merge_cells('A1:A2')

    contentAbstractCell = ws["B1"]
    contentAbstractCell.value = "内容简介"
    ws.merge_cells('B1:B2')

    resTypeCell = ws["C1"]
    resTypeCell.value = "资源类型"
    ws.merge_cells('C1:C2')

    isSeriesCell = ws["D1"]
    isSeriesCell.value = "是否是系列"
    ws.merge_cells('D1:D2')

    seriesCell = ws["E1"]
    seriesCell.value = "系列"
    ws.merge_cells('E1:F1')

    seriesNumCell = ws["E2"]
    seriesNumCell.value = "序号"

    seriesNameCell = ws["F2"]
    seriesNameCell.value = "名称"

    for eachCommonRow in ws.iter_rows("A1:L2"):
        logging.info("eachCommonRow=%s", eachCommonRow)
        for eachCellInRow in eachCommonRow:
            logging.info("eachCellInRow=%s", eachCellInRow)
            eachCellInRow.style = NamedStyleCommonHeader

initOutputExcelHeaders(wsStorybook)
initOutputExcelHeaders(wsSong)
wbOut.save(OutputUnifiedFormatExcelFilename)

效果：

确保指定的字体系统中是存在的

设置的Font确保是系统中存在的字体才可以

此处用的是Python2，系统中当前的字体名是微软雅黑

对应设置字体为雅黑的代码是

fontYahei12 = Font(name=u'微软雅黑', bold=True, size=12)

其中重点是：font的name是unicode才可以

估计内容原因是：如果name不是unicode，则name找不到，所以会报错，会导致excel打不开

此处微软雅黑字体的效果是：

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:39:15

常见问题

常见问题

警告：发现xlsx中的部分内容有问题。是否让我们尽量尝试恢复? 如果信任此工作簿的源，请单击"是"

背景：

用openpyxl去创建新excel文件，并从某原有excel中拷贝数据到新excel中

其中包括保留原先的合并后的单元格，比如：

相关代码是：

def keepPrevMergedCells(wsIn, wsInCurCellRange, wsInCurRowNum, wsOut, wsOutColNum):
    """
        keep original excel’s merged cells
    """
    logging.info("keepPrevMergedCells: wsIn=%s, wsInCurCellRange=%s, wsInCurRowNum=%s, wsOut=%s, wsOutColNum=%s",
                 wsIn, wsInCurCellRange, wsInCurRowNum, wsOut, wsOutColNum)

    cellRangeValue = crifanLib.getCellRangeValue(wsIn, wsInCurCellRange)
    rangeMinRow = wsInCurCellRange.min_row
    rangeMinCol = wsInCurCellRange.min_col
    rangeMaxRow = wsInCurCellRange.max_row
    rangeMaxCol = wsInCurCellRange.max_col
    logging.info("curCellRange: min_row=%s, min_col=%s, max_row=%s, max_row=%s",
                 rangeMinRow, rangeMinCol, rangeMaxRow, rangeMaxCol)
    rowNumDiff = wsInCurRowNum – rangeMinRow
    logging.info("rowNumDiff=%s", rowNumDiff)
    curStartCol = wsOutColNum
    curEndCol = wsOutColNum + (rangeMaxCol – rangeMinCol)
    logging.info("curStartCol=%s, curEndCol=%s", curStartCol, curEndCol)
    if rowNumDiff > 1:
        wsOut.unmerge_cells(start_row=rangeMinRow,
                                     start_column=curStartCol,
                                     end_row=wsInCurRowNum – 1,
                                     end_column=curEndCol)
    wsOut.merge_cells(start_row=rangeMinRow,
                       start_column=curStartCol,
                       end_row=wsInCurRowNum,
                       end_column=curEndCol)

打开保存后的excel文件后报错：

发现 xlsx 中的部分内容有问题。是否让我们尽量尝试恢复? 如果信任此工作簿的源，请单击“是”。

点击是，然后再点击删除：

是可以打开的，且貌似数据也是对的：

调试过程：

点击查看，是打开了xml文件：

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><logFileName>修复结果到 xxx2100.xml</logFileName><summary>在文件“/Users/xxx210.xlsx”中检测到错误</summary><removedRecords summary="以下是已删除记录的列表:"><removedRecord>已删除的记录: /xl/worksheets/sheet1.xml 部分的 合并单元格</removedRecord></removedRecords></recoveryLog>

最终调试到的现象是：

720行没问题

但是750行出问题

然后去原先文件看看是否有什么异常的情况：

最后找到了是原先的excel中的702 - 727行R列中：

是合并的单元格，但是内容却是空=None

根本原因：代码生成的excel中，某些单元格的值是无效的None，无法被Excel软件所识别

解决办法

（不太推荐）办法1：忽略之

根据提示，正常打开excel，点击删除，会删除对应无效的值

后续即可正常使用excel文件

（推荐）方法2：代码生成时，不要设置（Excel软件不支持的）None等值

即可彻底规避掉，不会产生此问题

修复后的相关代码是

def keepPrevMergedCells(wsIn, wsInCurCellRange, wsInCurRowNum, wsOut, wsOutColNum):
    """
        keep original excel’s merged cells
        if merged cell range itself value is None, should NOT keep merged
        otherwise will cause generated excel file corrupted
    """
    logging.info("keepPrevMergedCells: wsIn=%s, wsInCurCellRange=%s, wsInCurRowNum=%s, wsOut=%s, wsOutColNum=%s",
                wsIn, wsInCurCellRange, wsInCurRowNum, wsOut, wsOutColNum)

    cellRangeValue = crifanLib.getCellRangeValue(wsIn, wsInCurCellRange)
    if not cellRangeValue:
        logging.warning("Not keep previous None or empty value of merged cells")
        return
    # then wsOut.unmerge_cells and wsOut.merge_cells is ok

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:40:00

xlrd和xlwt

xlrd和xlwt

下载和安装

xlrd

从

http://pypi.python.org/pypi/xlrd

下载，最新版本的

xlrd-0.8.0.tar.gz

得到130KB的xlrd-0.8.0.tar.gz

解压后，打开cmd切换到对应目录，去执行

setup.py install

xlwt

从主页：

http://pypi.python.org/pypi/xlwt

下载xlwt-0.7.4.tar.gz后，解压

切换到对应目录后，去安装：

setup.py install

xlutils

从主页：

http://pypi.python.org/pypi/xlutils

下载

xlutils-1.5.2.tar.gz

得到47KB的xlutils-1.5.2.tar.gz

解压后，切换到对应目录后，去安装：

setup.py install

基本操作

概述：

新建excel文件

代码

import xlwt
from datetime import datetime

style0 = xlwt.easyxf('font: name Times New Roman, color-index red, bold on',num_format_str='#,##0.00')
style1 = xlwt.easyxf(num_format_str='D-MMM-YY')

wb = xlwt.Workbook()
ws = wb.add_sheet('A Test Sheet')

ws.write(0, 0, 1234.56, style0)
ws.write(1, 0, datetime.now(), style1)
ws.write(2, 0, 1)
ws.write(2, 1, 1)
ws.write(2, 2, xlwt.Formula("A3+B3"))

wb.save('example.xls')

效果

追加写入新数据

背景：想要添加写入数据到已经存在的Excel的xls文件，即打开excel文件，写入新数据

解决办法

想要往已经存在的xls文件中，写入新的行，新的数据，对应的逻辑为：

用xlrd.open_workbook打开已有的xsl文件

注意：添加参数formatting_info=True，得以保存之前数据的格式

然后用from xlutils.copy import copy拷贝出原有数据

copy去从打开的xlrd的Book变量中，拷贝出一份，成为新的xlwt的Workbook变量

对xlwt的Workbook变量的正常的操作

通过get_sheet去获得对应的sheet

拿到sheet变量后，就可以往sheet中，写入新的数据

写完新数据后，最终save保存

代码

import xlwt
import xlrd
#import xlutils
from xlutils.copy import copy

styleBoldRed   = xlwt.easyxf('font: color-index red, bold on')
headerStyle = styleBoldRed
wb = xlwt.Workbook()
ws = wb.add_sheet(gConst['xls']['sheetName'])
ws.write(0, 0, "Header",        headerStyle)
ws.write(0, 1, "CatalogNumber", headerStyle)
ws.write(0, 2, "PartNumber",    headerStyle)
wb.save(gConst['xls']['fileName'])

#open existed xls file
#newWb = xlutils.copy(gConst['xls']['fileName'])
#newWb = copy(gConst['xls']['fileName'])
oldWb = xlrd.open_workbook(gConst['xls']['fileName'], formatting_info=True)
print oldWb #<xlrd.book.Book object at 0x000000000315C940>
newWb = copy(oldWb)
print newWb #<xlwt.Workbook.Workbook object at 0x000000000315F470>
newWs = newWb.get_sheet(0)
newWs.write(1, 0, "value1")
newWs.write(1, 1, "value2")
newWs.write(1, 2, "value3")
print "write new values ok"
newWb.save(gConst['xls']['fileName'])
print "save with same name ok"

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:41:26

常见问题

常见问题

AttributeError: 'module' object has no attribute 'copy'

背景

代码：

import xlutils

newWb = xlutils.copy(gConst['xls']['fileName'])

报错：

AttributeError: 'module' object has no attribute 'copy'

原因：未知。可能是库本身的bug。

解决办法

改为：

from xlutils.copy import copy

newWb = copy(gConst['xls']['fileName'])

即可（规避此问题）

AttributeError: 'str' object has no attribute 'datemode'

背景

代码：

from xlutils.copy import copy;

newWb = copy(gConst['xls']['fileName'])

出错：

   newWb = copy(gConst['xls']['fileName']);
  File "D:\tmp\dev_install_root\Python27_x64\lib\site-packages\xlutils-1.5.2-py2.7.egg\xlutils\copy.py", line 13, in copy
    w
  File "D:\tmp\dev_install_root\Python27_x64\lib\site-packages\xlutils-1.5.2-py2.7.egg\xlutils\filter.py", line 827, in process
    reader(chain[0])
  File "D:\tmp\dev_install_root\Python27_x64\lib\site-packages\xlutils-1.5.2-py2.7.egg\xlutils\filter.py", line 60, in __call__
    filter.workbook(workbook,filename)
  File "D:\tmp\dev_install_root\Python27_x64\lib\site-packages\xlutils-1.5.2-py2.7.egg\xlutils\filter.py", line 267, in workbook
    self.wtbook.dates_1904 = rdbook.datemode
AttributeError: 'str' object has no attribute 'datemode'

原因：参考官网的资料 xlutils copy，才知道copy的参数，是对应的workbook，而不是xls的filename

解决办法：先从excel文件中（通过xlrd）读取得到workbook，再去用copy

代码

import xlwt
import xlrd
#import xlutils
from xlutils.copy import copy

oldWb = xlrd.open_workbook(gConst['xls']['fileName'])
print oldWb; #<xlrd.book.Book object at 0x000000000315C940>
newWb = copy(oldWb)
print newWb; #<xlwt.Workbook.Workbook object at 0x000000000315F470>

才真正可以正常打开旧的xls，拷贝出一份新的xls

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:41:09

pandas

pandas

Python的科学计算方面的库，主要用于数据处理的pandas，也可以操作excel和csv

pandas

官网API文档

Excel

读：pandas.read_excel

pandas.read_excel — pandas 1.2.4 documentation

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_excel.html

语法

pandas.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, usecols=None, squeeze=False, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, parse_dates=False, date_parser=None, thousands=None, comment=None, skipfooter=0, convert_float=True, mangle_dupe_cols=True, storage_options=None)

写：pandas.DataFrame.to_excel

pandas.DataFrame.to_excel — pandas 1.2.4 documentation

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_excel.html

语法

DataFrame.to_excel(excel_writer, sheet_name='Sheet1', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, startrow=0, startcol=0, engine=None, merge_cells=True, encoding=None, inf_rep='inf', verbose=True, freeze_panes=None, storage_options=None)[source]

csv

读：pandas.read_csv

pandas.read_csv — pandas 1.2.4 documentation

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

语法

pandas.read_csv(filepath_or_buffer, sep=<object object>, delimiter=None, header='infer', names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression='infer', thousands=None, decimal='.', lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, dialect=None, error_bad_lines=True, warn_bad_lines=True, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None, storage_options=None)[source]

写：pandas.DataFrame.to_csv

pandas.DataFrame.to_csv — pandas 1.2.4 documentation

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html

语法

DataFrame.to_csv(path_or_buf=None, sep=',', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, mode='w', encoding=None, compression='infer', quoting=None, quotechar='"', line_terminator=None, chunksize=None, date_format=None, doublequote=True, escapechar=None, decimal='.', errors='strict', storage_options=None)

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:41:31

win32com.client

win32com.client

此处用win32com.client去处理Excel中的图表，比如Chart、Graph等。

处理Excel的图表

在当前文件夹中新建一个空的xls文件：chart_demo.xls

用（Python 2的）代码：

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Function:
【已解决】Python中处理操作Excel中的图表（Chart，Graph）
https://www.crifan.com/python_process_excel_chart_graph

Author:     Crifan Li
Version:    2012-12-25
Contact:    admin at crifan dot com
"""

import os
from win32com.client import Dispatch
#from win32com.client import *

def excelChart():
    xl = Dispatch("Excel.Application")
    #xl = win32com.client.Dispatch("Excel.Application")
    print "xl=",xl

    #[1] Fail
    # xlsPath = "chart_demo.xls"
    # wb = xl.Workbooks.open(xlsPath) #pywintypes.com_error

    #[2] Fail
    # xlsPath = "D:\tmp\tmp_dev_root\python\excel_chart\chart_demo.xls"
    # absPath = os.path.abspath(xlsPath)
    # print "absPath=",absPath #absPath= D:\tmp\tmp_dev_root\python\excel_chart\        mp      mp_dev_root\python\excel_chart\chart_demo.xls
    # wb = xl.Workbooks.open(absPath) #pywintypes.com_error

    #[3] Fail
    # xlsPath = "D:\tmp\tmp_dev_root\python\excel_chart\chart_demo.xls"
    # normalPath = os.path.normpath(xlsPath)
    # print "normalPath=",normalPath #normalPath= D:  mp      mp_dev_root\python\excel_chart\chart_demo.xls
    # wb = xl.Workbooks.open(normalPath) #pywintypes.com_error

    #[4] Fail
    # rawPath = r"chart_demo.xls"
    # wb = xl.Workbooks.open(rawPath) #pywintypes.com_error

    #[5] OK
    xlsPath = "chart_demo.xls"
    absPath = os.path.abspath(xlsPath)
    print "absPath=",absPath #absPath= D:\tmp\tmp_dev_root\python\excel_chart\chart_demo.xls
    wb = xl.Workbooks.open(absPath) #OK

    #[6] OK
    # rawPath = r"D:\tmp\tmp_dev_root\python\excel_chart\chart_demo.xls"
    # wb = xl.Workbooks.open(rawPath) # OK

    xl.Visible = 1
    ws = wb.Worksheets(1)
    ws.Range('$A1:$D1').Value = ['NAME', 'PLACE', 'RANK', 'PRICE']
    ws.Range('$A2:$D2').Value = ['Foo', 'Fooland', 1, 100]
    ws.Range('$A3:$D3').Value = ['Bar', 'Barland', 2, 75]
    ws.Range('$A4:$D4').Value = ['Stuff', 'Stuffland', 3, 50]
    wb.Save()
    wb.Charts.Add()
    wc1 = wb.Charts(1)

if __name__ == "__main__":
    excelChart()

效果：

Excel单元格内容

Excel对应图表效果

常见问题

ImportError: No module named win32com.client

代码：

from win32com.client import Dispatch

会报错：

D:\tmp\tmp_dev_root\python\excel_chart>excel_chart.py
Traceback (most recent call last):
  File "D:\tmp\tmp_dev_root\python\excel_chart\excel_chart.py", line 13, in <module>
    from win32com.client import Dispatch
ImportError: No module named win32com.client

解决办法：下载和安装pywin32

具体步骤

去

http://sourceforge.net/projects/pywin32/files/pywin32/

下载

http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/

此处Win7 64位 + Python 2.7.3对应的版本：

pywin32-218.win-amd64-py2.7.exe

然后去双击安装，一路默认设置：

即可。

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:42:40

附录

附录

下面列出相关参考资料。

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:38:27

参考资料

参考资料

【已解决】Python中如何读取csv文件中每一行的数据

【整理】用Python把列表或字典数据输出写入csv文件

【已解决】python的输出列表数据到csv但没有表头

【已解决】Python中创建和保存数据到csv文件中

【已解决】python解析excel文件并读取其中的sheet和row和column的值

【已解决】openpyxl中给单元格设置背景色

【部分解决】openpyxl的excel设置列宽自适应+设置行高 – 在路上

【已解决】openpyxl中设置单元格自动换行

【已解决】openpyxl中给一个范围内的单元格批量设置样式：居中对齐和背景色

【已解决】用openpyxl去新建excel文件并保存数据和设置单元格样式

【已解决】openpyxl代码警告：Using a range string with iter_rows is deprecated. Use ws[range_string]

【已解决】openpyxl生成excel文件打开提示：发现xlsx中的部分内容有问题 是否让我们尽量尝试恢复

【已解决】Python中openpyxl处理excel去判断单元格是合并后的以及合并的范围

【整理】Python中，添加写入数据到已经存在的Excel的xls文件，即打开excel文件，写入新数据 – 在路上

【记录】Python中生成（写入数据到）Excel文件中

【记录】Python中安装xlrd模块

【记录】Python中安装可以读写excel的xls文件的xlutils模块（需依赖于xlrd和xlwt）

【已解决】Python中处理操作Excel中的图表（Chart，Graph） – 在路上

【已解决】Python中出错：ImportError: No module named win32com.client – 在路上

【记录】Mac中用Python去解析excel文件 – 在路上

【已解决】Mac中安装Python的第三方库：openpyxl

【整理】python中处理excel的库xlrd和xlwt的python 3.x版本是：xlrd3和xlwt3 – 在路上

【已解决】Python中使用xlutils.copy出错：AttributeError: ‘module’ object has no attribute ‘copy’ – 在路上

【已解决】Python中使用xlutils的copy出错：AttributeError: ‘str’ object has no attribute ‘datemode’ – 在路上

第 6 章 Python中的CSV,Excel

【python】pandas库pd.read_excel操作读取excel文件参数整理与实例_brucewong0516的博客-CSDN博客

最新Pandas.read_excel()全参数详解（案例实操，如何利用python导入excel） - 知乎

pandas.read_excel 详细介绍 | Pandas 中文教程 - 盖若

Python Resources for working with Excel - Working with Excel Files in Python

请教下 Python 高手，如何用 Python 自动化操作 Excel？ - 知乎

python - How to write header row with csv.DictWriter? - Stack Overflow

Openpyxl tutorial - read, write Excel xlsx files in Python

crifan.com，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2021-04-13 20:38:32