φυβλαςのβλογ
phyblas的博客



การอ่านข้อมูลในไฟล์ microsoft excel ด้วย xlrd ใน python
เขียนเมื่อ 2020/06/06 00:27
แก้ไขล่าสุด 2024/02/22 05:53
 



ไพธอนมีมอดูหลายตัวที่เอาไว้เปิดอ่านไฟล์สกุล .xlsx หรือ .xls ซึ่งเป็นไฟล์เอ็กซ์เซล (excel)

สำหรับบทความนี้จะแนะนำมอดูล xlrd ซึ่งเป็นมอดูลสำหรับอ่านไฟล์เอ็กซ์เซลที่นิยมมากตัวหนึ่ง

ก่อนหน้านี้ในบทความหน้า https://phyblas.hinaboshi.com/20200605 ได้แนะนำมอดูล openpyxl ซึ่งเป็นมอดูลที่ใช้สำหรับจัดการไฟล์ .xlsx ทำได้ทั้งอ่านและเขียน

อย่างไรก็ตาม openpyxl ไม่สามารถใช้อ่านไฟล์ .xls ซึ่งเป็นไฟล์เอ็กซ์เซลรุ่นเก่ารุ่น 2003 ลงมาได้

ในขณะที่ xlrd สามารถอ่านได้ทั้ง .xls และ .xlsx อีกทั้งยังทำงานค่อนข้างเร็วกว่า openpyxl ด้วย

เพียงแต่ xlrd มีไว้ใช้อ่านไฟล์เอ็กซ์เซลเท่านั้น ไม่สามารถเขียนใหม่หรือแก้ไขไฟล์ได้ จึงเหมาะที่จะใช้ในเวลาที่แค่ต้องการอ่านเอาข้อมูลแต่ไม่ได้จะแก้อะไร

นอกจากนี้ยังมีมอดูล xlwt เอาไว้เขียนหรือแก้ไขไฟล์เอ็กซ์เซล ซึ่งมักใช้คู่กับ xlrd คนสร้างก็คนเดียวกัน

แต่เมื่อต้องการเขียนหรือแก้ไขไฟล์แนะนำให้ใช้ openpyxl มากกว่า ดังนั้นในที่นี้จะขอแนะนำแค่การใช้ xlrd ไม่เขียนถึง xlrt ซึ่งน่าจะมีโอกาสได้ใช้น้อยกว่า แต่วิธีการใช้ xlrt เองก็มีส่วนคล้าย openpyxl อยู่




การติดตั้ง

เช่นเดียวกับ openpyxl หรือมอดูลอื่นๆที่ใช้จัดการไฟล์เอ็กซ์เซล xlrd ก็ไม่ใช่มอดูลมาตรฐานที่มีอยู่ตั้งแต่แรกในไพธอน จึงต้องทำการติดตั้งเพิ่มเติมเอง ซึ่งการติดตั้งก็ทำได้ง่ายโดยอาจใช้ pip หรือ conda
pip install xlrd
conda install xlrd




การเปิดไฟล์เอ็กซ์เซลและเลือกแผ่นงาน

การใช้งาน xlrd เริ่มจากใช้ฟังก์ชัน xlrd.open_workbook() เพื่ออ่านสมุดงานจากไฟล์

ภายในไฟล์หนึ่งอาจประกอบไปด้วยตารางแผ่นงาน (worksheet) หลายแผ่น ถ้าดูในโปรแกมไมโครซอฟต์เอ็กซ์เซลโดยตรงก็จะเห็นแถบเลือกแผ่นงานอยู่ด้านล่าง กด + เพื่อเพิ่มได้

เช่นไฟล์ในภาพนี้ มี ๓ แผ่นชื่อ Sheet1, Sheet2, Sheet3



หากใช้เมธอด .sheet_names() ที่ออบเจ็กต์ตัวสมุดงานจะแสดงชื่อของแผ่นงานทั้งหมด ลองเปิดขึ้นมาดูแผ่นงานทั้งหมดในนี้ได้
wb = xlrd.open_workbook('khomun.xlsx')
print(wb.sheet_names()) # ได้ ['Sheet1', 'Sheet2', 'Sheet3']

ถ้าใช้เมธอด .sheets() จะได้ลิสต์ของออบเจ็กต์ของตัวแผ่นงานทั้งหมดมา นำมาใช้ได้ เช่นจะเอาออบเจ็กต์ตัวแผ่นงานแผ่นแรกอาจเขียนเป็น
tarang = wb.sheets()[0]

นอกจากนี้อาจใช้เมธอด .sheet_by_index() โดยระบุเลขลำดับของแผ่นงานที่ต้องการเลือก เช่น
tarang = wb.sheet_by_index(0)

หรือใช้เมธอด .sheet_by_name() โดยระบุชื่อของของแผ่นงานที่ต้องการเลือก เช่น
tarang = wb.sheet_by_name('Sheet1')




การเอาข้อมูลในแต่ละช่อง

ตารางในแผ่นงานแต่ละตารางก็จะประกอบด้วยช่องต่างๆมากมาย โดยแบ่งเป็นแถว (row) ตามแนวตั้ง แบ่งเป็นสดมภ์ (column) ตามแนวนอน

วิธีการเข้าถึงข้อมูลภายในตารางมีอยู่หลายวิธีด้วยกัน ในที่นี้จะกล่าวถึงแต่ละวิธีที่ปกติมักจะใช้กัน

วิธีแรกคือ หากต้องการข้อมูลแค่จากตำแหน่งหนึ่งใดในตารางมาเลยก็อาจใช้เมธอด .cell(แถว,สดมภ์) หรือ .cell_value(แถว,สดมภ์) โดยเลขแสดงแถวและสดมภ์นั้นเริ่มไล่จาก 0 จึงไม่ได้ตรงกับเลขแถวจริงในตารางซึ่งเริ่มจาก 1 แต่จะน้อยกว่าอยู่ 1 เสมอ และเลขสดมภ์ 0,1,2 จะตรงกับสดมภ์ A,B,C ตามลำดับ

.cell() จะให้ออบเจ็กต์ตัวช่องมา ถ้าเอามาดูพรอเพอร์ตี .value จึงจะได้ตัวค่านั้นมา ส่วน .cell_value() จะให้ค่ามาเลย

สมมุติว่าข้อมูลภายในตารางแรก Sheet1 เป็นแบบนี้



โดยที่แถว C เป็นค่าที่ได้จากการคำนวณเอาค่าแถว A และ B มาคูณกันตามสมการที่เขียน (เช่น ในที่นี้ 16×17=272)

ในการใช้ xlrd อ่านค่านั้น ค่าที่อ่านได้จะเป็นค่าผลลัพธ์นั้นเลย ไม่ใช่ตัวสมการที่เขียนลงไป

ตัวอย่างการใช้ ลองอ่านข้อมูลในตารางนี้ขึ้นมาดู
wb = xlrd.open_workbook('khomun.xlsx')
tarang = wb.sheets()[0]
print(tarang.cell(1,0)) # ได้ number:4.0
print(tarang.cell(2,1).value) # ได้ 10.0
print(tarang.cell_value(3,2)) # ได้ 272.0

หากต้องการไล่เอาข้อมูลทั้งตาราง อาจใช้ for วนไล่ดูทุกแถวทุกสดมภ์

จำนวนแถวและสดมภ์ที่มีทั้งหมดสามารถดูได้จากพรอเพอร์ตี .nrows และ .ncols เช่น
print(tarang.nrows) # ได้ 4
print(tarang.ncols) # ได้ 3

เมื่อรู้จำนวนแถวและสดมภ์แล้วก็สามารถเอามาวนซ้ำด้วย for ๒ ชั้นเพื่อเข้าถึงข้อมูลทั้งหมดได้ เช่น
kha = []
for i in range(tarang.nrows):
    for j in range(tarang.ncols):
        kha.append(tarang.cell_value(i,j))

print(kha) # ได้ [1.0, 2.0, 2.0, 4.0, 5.0, 20.0, 9.0, 10.0, 90.0, 16.0, 17.0, 272.0]

อีกวิธีคือดูทีเดียวเป็นแถวๆ โดยใช้เมธอด .row หรือ row_values เพื่อดึงข้อมูลทั้งแถวออกมาทีเดียว หรือดูไปทีละสดมภ์โดยใช้เมธอด .col หรือ col_values เพื่อดึงข้อมูลทั้งสดมภ์ออกมาทีเดียว ผลที่ได้จะอยู่ในรูปลิสต์

เมธอดที่ชื่อมี _values ต่อท้ายนั้นจะได้ตัวค่าในช่องนั้นมาทันทีเลย ส่วนที่ไม่มี _values จะเป็นแค่การเอาออบเจ็กต์ช่องมา ต้องมาเอาค่าจากพรอเพอร์ตี .value อีกที

ตัวอย่าง
print(tarang.row(2)) # ได้ [number:9.0, number:10.0, number:90.0]
print(tarang.row(2)[1].value) # ได้ 10.0
print(tarang.row_values(3)) # ได้ [16.0, 17.0, 272.0]
print(tarang.col(0)) # ได้ [number:1.0, number:4.0, number:9.0, number:16.0]
print(tarang.col_values(2)) # ได้ [2.0, 20.0, 90.0, 272.0]

นอกจากนี้ยังมีอีกวิธีคือ ใช้เมธอด .get_rows() เพื่อสร้างเป็นเจเนอเรเตอร์มาวนซ้ำด้วย for ให้ได้ลิสต์ของข้อมูลทุกสดมภ์ของทีละแถวได้ เช่น
for row in tarang.get_rows():
    print(row)

ได้
[number:1.0, number:2.0, number:2.0]
[number:4.0, number:5.0, number:20.0]
[number:9.0, number:10.0, number:90.0]
[number:16.0, number:17.0, number:272.0]




การแปลงเป็น .csv

หากแค่ต้องการเก็บข้อมูลเป็นตารางเฉยๆ ไม่ได้สนรูปแบบตัวอักษรหรือขนาดตาราง แบบนั้นเก็บในรูปของ .csv จะสะดวกกว่าที่จะใช้เอ็กซ์เซล ทั้งอ่านง่ายกว่า และสามารถดูข้อมูลข้างในโดยตรงได้โดยไม่ต้องใช้โปรแกรมช่วยอะไร

การแปลงจากไฟล์เอ็กซ์เซลเป็น .csv อาจทำได้ง่ายโดยการใช้มอดูล xlrd คู่กับมอดูล csv ซึ่งเป็นมอดูลที่มีอยู่แล้วในไพธอน (รายละเอียดของมอดูลนี้ดูได้ที่ https://phyblas.hinaboshi.com/20190810)

ตัวอย่างเช่น หากต้องการดึงข้อมูลทุกแถวทุกสดมภ์จากตารางในแผ่นงานแผ่นแรกในไฟล์มาบันทึกใส่ .csv อาจเขียนแบบนี้
import xlrd,csv

wb = xlrd.open_workbook('khomun.xlsx')
tarang = wb.sheets()[0]
with open('khomun.csv','w') as f:
    wr = csv.writer(f)
    for i in range(tarang.nrows):
        wr.writerow(tarang.row_values(i))

แล้วก็จะได้ไฟล์ khomun.csv ออกมาเป็นแบบนี้
1.0,2.0,2.0
4.0,5.0,20.0
9.0,10.0,90.0
16.0,17.0,272.0




การจัดการกับข้อมูลวันที่

ในโปรแกรมเอ็กซ์เซล ถ้าเขียนข้อมูลวันเวลาไปในรูป ปี/เดือน/วัน ไปในตาราง มันจะถูกตีความเป็นวันที่ให้เลย แล้วพอเปิดอ่านด้วย xlrd ค่าที่ได้จะไม่ใช่ตัววันเวลา แต่เป็นเลข timestamp ที่แทนวันนั้น

การจะเอามาใช้จำเป็นต้องทำการแปลงเป็นวันที่ก่อน โดยใน xlrd ก็ได้มีเตรียมฟังก์ชันสำหรับแปลงตรงนี้ไว้ให้

ฟังก์ชัน xlrd.xldate_as_datetime() จะแปลง timestamp ให้เป็นออบเจ็กต์ datetime ของไพธอน

เกี่ยวกับ datetime นี้ดูรายละเอียดได้ใน https://phyblas.hinaboshi.com/20160621

ส่วนฟังก์ชัน xlrd.xldate_as_tuple() จะแปลง timestamp เป็นทูเพิลของ (ปี,เดือน,วัน,ชั่วโมง,นาที,วินาที)

ทั้ง ๒ ฟังก์ชันนี้ต้องใส่เวลา timestamp เป็นอาร์กิวเมนต์ตัวแรก และใส่โหมดของเวลาเป็นอาร์กิวเมนต์ตัวถัดมา โดยโหมดของเวลานี้เป็นค่าที่ถูกเก็บอยู่ในไฟล์และเมื่ออ่านขึ้นมาด้วย xlrd.open_workbook() ก็จะถูกเก็บอยู่ในพรอเพอร์ตี .datemode ออบเจ็กต์สมุดงานนั้น

ยกตัวอย่าง สมมุติว่าในไฟล์ khomun.xlsx มีข้อมูลในหน้าที่ ๒ เป็นแบบนี้



ลองอ่านสดมภ์ที่เขียนวันที่ไว้
wb = xlrd.open_workbook('khomun.xlsx')
tarang2 = wb.sheets()[1]
wan = tarang2.cell(3,0)
print(wan) # ได้ xldate:43982.0
print(xlrd.xldate_as_datetime(wan.value,wb.datemode)) # ได้ 2020-05-31 00:00:00

wan = tarang2.cell(4,0)
print(wan) # ได้ xldate:43983.0
print(xlrd.xldate_as_tuple(wan.value,wb.datemode)) # ได้ (2020, 6, 1, 0, 0, 0)
print(xlrd.xldate_as_tuple(tarang2.cell_value(5,0),wb.datemode)) # ได้ (2020, 6, 2, 0, 0, 0)

ที่ ๓ ตัวหลังในทูเพิลเป็น 0 และเลขบอกเวลาเป็น 0 หมดเพราะในที่นี้ไม่ได้ใส่เลขเวลา แต่ถ้าใส่ไปด้วยก็จะได้เวลาออกมาตามนั้นเช่นกัน

ลองใช้ for วนซ้ำไล่ดูข้อมูลไปทีละแถว
for i in range(tarang2.nrows):
    wan,n = tarang2.row_values(i)
    print('%d/%d/%d: %d'%(*xlrd.xldate_as_tuple(wan,wb.datemode)[:3],n))

ได้
2020/5/28: 11
2020/5/29: 11
2020/5/30: 1
2020/5/31: 4
2020/6/1: 1
2020/6/2: 1
2020/6/3: 1
2020/6/4: 17
2020/6/5: 1




อ้างอิง


-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python
-- คอมพิวเตอร์ >> microsoft_office

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

目录

从日本来的名言
模块
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
机器学习
-- 神经网络
javascript
蒙古语
语言学
maya
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  查看日志

  推荐日志

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ