django導入導出excel實踐

1、xlrd和xlwt模塊介紹

   xlrd模塊提供在任何平臺上從excel電子表格(.xls和.xlsx)中提取數據的功能,xlwt模塊提供生成與Microsoft Excel 95 到2003版本兼容的excel文件的功能。html

一、安裝方法

# 方法一:
pip3 install xlrd
pip3 install xlwt

# 方法二:
    在python官網http://pypi.python.org/pypi/xlrd/(xlwt)下載xlrd/xlwt的安裝包。
    壓縮包放置在python安裝目錄下python/Lib/site-packages。
    解壓壓縮包:tar zxvf xlrd-1.0.0.tar.gz
    進入到解壓的文件夾:cd xlrd-1.0.0
    執行命令:python setup,py install

二、xlrd使用詳解

(1)excel文檔準備

  準備excel文檔:聯繫人.xls,內容以下所示:python

  

  

(2)xlrd獲取sheet工做表名稱和對象

import xlrd

# 打開Excel文件讀取器,加上utf-8編碼可防止遇到中文字符亂碼
data = xlrd.open_workbook('聯繫人.xls', encoding_override='utf-8')

# 獲取全部sheet工做表名稱
sheetnames = data.sheet_names()
print(sheetnames)
"""
['銀行1', '銀行2']
"""
# 經過索引獲取指定sheet工做表名稱
sheet_name = data.sheet_names()[1]
print(sheet_name)
"""
銀行2
"""
# 經過工做表名稱獲取sheet對象
table_name = data.sheet_by_name(sheet_name)
print(table_name)
"""
<xlrd.sheet.Sheet object at 0x10b657160>
"""
# 經過sheet索引獲取sheet工做表對象
table_index = data.sheet_by_index(0)
print(table_index)
"""
<xlrd.sheet.Sheet object at 0x1073b3f28>
"""

(3)sheet工做錶行/列操做

# 獲取行數和列數
nrows = table_name.nrows     # 總行數
ncols = table_name.ncols     # 總列數
print("銀行2表,總行數: %s,總列數: %s" % (nrows, ncols))
"""
銀行2表,總行數: 5,總列數: 7
"""
# 根據sheet對象獲取整行和整列的值
sheet_row_val = table_name.row_values(3)
sheet_col_val = table_name.col_values(3)
print("整行的值:%s , \n整列的值: %s" % (sheet_row_val, sheet_col_val))
"""
整行的值:['', '李九', '開發', 'IOS開發', 87888.0, 13213123.0, 'wang1@164.com'] , 
整列的值: ['', '工做職責', 'UI設計', 'IOS開發', '硬件維護']
"""
# 獲取當前行的有效單元格長度
print(table_name.row_len(3))
print(table_index.row_len(3))
"""
7
8
"""

(4)sheet工做表單元格操做

  單元格是組成表格的最小單位,能夠拆分或合併。每一個數據的輸入和修改都是在單元格中進行的。數據庫

# 獲取指定單元格內容
print(table_name.cell(1,0).value)    # 第二行第一列
print(table_name.cell_value(2,1))    # 第三行第二列
print(table_name.row(1)[0].value)    # 第二行第一列
"""
機構名稱
張八
機構名稱
"""
# 獲取單元格內容的數據類型
# ctype說明:0 empty, 1 string, 2 number, 3 date, 4 boolean, 5 error
print(table_index.cell(1,0).ctype)   # 銀行1表,2行1列內容  機構名稱
print(table_index.cell(3,4).ctype)   # 銀行1表,4行5列內容  888
print(table_index.cell(2,6).ctype)   # 銀行1表,3行7列內容  2019/5/7
"""
1
2
3
"""
# 日期單元格內容處理
from datetime import datetime, date
if table_index.cell(2,6).ctype == 3:
    print(table_index.cell(2, 6).value)
    date_value = xlrd.xldate_as_tuple(table_index.cell(2, 6).value, data.datemode)
    print(date_value)
    print(date(*date_value[:3]))
    print(date(*date_value[:3]).strftime('%Y/%m/%d'))
"""
43592.0
(2019, 5, 7, 0, 0, 0)
2019-05-07
2019/05/07
"""
# 獲取number類型的單元格內容
if table_index.cell(3, 4).ctype == 2:
    print(table_index.cell(3, 4).value)
    num_value = int(table_index.cell(3, 4).value)   # 轉爲整型
    print(num_value)
"""
888.0
888
""" 

(5)獲取合併單元格內容

  須要使用merged_cells屬性,獲取merged_cells返回的row和col低位的索引便可。django

# 須要在讀取文件時添加formatting_info參數,默認是False
# 須要設置爲True,才能調用merged_cells屬性獲取到值
xls_data = xlrd.open_workbook('聯繫人.xls', formatting_info=True)
sheet_data = xls_data.sheet_by_name('銀行2')
print(sheet_data.merged_cells)
"""
[(0, 1, 0, 7), (2, 5, 0, 1)]
"""

  merged_cells返回的這四個參數的含義:(row,row_range,col,col_range)。session

  所以,(0,1,0,7)表示第1列~第7列合併;(2,5,0,1)表示第3行~第6行合併。app

# 分別獲取合併兩個單元格內容
merge_value = []
for (row, row_range, col, col_range) in sheet_data.merged_cells:
    merge_value.append((row, col))
"""
[(0, 0), (2, 0)]
"""
print(merge_value)
for i in merge_value:
    print(sheet_data.cell(i[0], i[1]).value)
"""
銀行2
銀行2
"""

三、xlwt使用詳解

  使用xlwt模塊對Excel文件進行建立、設置、保存等操做。ide

import xlwt

# 建立一個工做簿(workbook),並設置編碼
# workbook = xlwt.Workbook(encoding='ascii')
workbook = xlwt.Workbook(encoding='utf-8')

# 建立一個工做表(worksheet)
worksheet = workbook.add_sheet("My Worksheet")

# 樣式設置(可選)
style = xlwt.XFStyle()   # 初始化樣式
font = xlwt.Font()       # 爲樣式建立字體
font.name = "Times New Roman"
font.bold = True         # 加粗
font.underline = True    # 下劃線
font.italic = True       # 斜體字
style.font = font        # 設定樣式

# 寫入excel,參數對應 行 列 值
# 不帶樣式的寫入
worksheet.write(1,0, 'Unformatted value')
# 帶樣式的寫入
worksheet.write(2,0, 'Formatted value', style)

# 保存文件
workbook.save("xlwt_test.xls")

  打開Excel文件顯示效果以下:函數

  

(1)設置單元格寬度

import xlwt

workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
worksheet.write(0, 0,'My Cell Contents')
# 設置單元格寬度
worksheet.col(0).width = 30003
workbook.save('cell_width.xls')

  顯示效果:post

  

(2)輸入日期到單元格

import xlwt
import datetime

workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')

style = xlwt.XFStyle()
style.num_format_str = 'M/D/YY' # Other options: D-MMM-YY, D-MMM, MMM-YY, h:mm, h:mm:ss, h:mm, h:mm:ss, M/D/YY h:mm, mm:ss, [h]:mm:ss, mm:ss.0

worksheet.write(0, 0, datetime.datetime.now(), style)
workbook.save('Excel_Workbook.xls')

  顯示效果:字體

  

(3)添加公式到單元格

import xlwt

workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
worksheet.write(0, 0, 5) # Outputs 5
worksheet.write(0, 1, 2) # Outputs 2

# 添加公式
worksheet.write(1, 0, xlwt.Formula('A1*B1')) # Should output "10" (A1[5] * A2[2])
worksheet.write(1, 1, xlwt.Formula('SUM(A1,B1)')) # Should output "7" (A1[5] + A2[2])

workbook.save('Excel_formula.xls')

  顯示效果:

  

(4)添加超連接到單元格

import xlwt

workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')

worksheet.write(0, 0, xlwt.Formula('HYPERLINK("http://www.baidu.com";"Baidu")')) # Outputs the text "Baidu" linking to http://www.baidu.com

workbook.save('Excel_hyperlink.xls')

  顯示效果:

  

(5)合併列和行

import xlwt

workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')

worksheet.write_merge(0, 0, 0, 3, 'First Merge') # Merges row 0's columns 0 through 3.
font = xlwt.Font() # Create Font
font.bold = True # Set font to Bold
style = xlwt.XFStyle() # Create Style
style.font = font # Add Bold Font to Style
worksheet.write_merge(1, 2, 0, 3, 'Second Merge', style) # Merges row 1 through 2's columns 0 through 3.
workbook.save('Excel_merge.xls')

  顯示效果:

  

(6)其餘單元格設置

"""
設置單元格內容的對其方式:
"""
import xlwt
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
alignment = xlwt.Alignment() # Create Alignment
alignment.horz = xlwt.Alignment.HORZ_CENTER # May be: HORZ_GENERAL, HORZ_LEFT, HORZ_CENTER, HORZ_RIGHT, HORZ_FILLED, HORZ_JUSTIFIED, HORZ_CENTER_ACROSS_SEL, HORZ_DISTRIBUTED
alignment.vert = xlwt.Alignment.VERT_CENTER # May be: VERT_TOP, VERT_CENTER, VERT_BOTTOM, VERT_JUSTIFIED, VERT_DISTRIBUTED
style = xlwt.XFStyle() # Create Style
style.alignment = alignment # Add Alignment to Style
worksheet.write(0, 0, 'Cell Contents', style)
workbook.save('Excel_Workbook.xls')

"""
爲單元格議添加邊框:
"""
# Please note: While I was able to find these constants within the source code, on my system (using LibreOffice,) I was only presented with a solid line, varying from thin to thick; no dotted or dashed lines.
import xlwt
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
borders = xlwt.Borders() # Create Borders
borders.left = xlwt.Borders.DASHED
  DASHED虛線
  NO_LINE沒有
  THIN實線
# May be: NO_LINE, THIN, MEDIUM, DASHED, DOTTED, THICK, DOUBLE, HAIR, MEDIUM_DASHED, THIN_DASH_DOTTED, MEDIUM_DASH_DOTTED, THIN_DASH_DOT_DOTTED, MEDIUM_DASH_DOT_DOTTED, SLANTED_MEDIUM_DASH_DOTTED, or 0x00 through 0x0D.
borders.right = xlwt.Borders.DASHED
borders.top = xlwt.Borders.DASHED
borders.bottom = xlwt.Borders.DASHED
borders.left_colour = 0x40
borders.right_colour = 0x40
borders.top_colour = 0x40
borders.bottom_colour = 0x40
style = xlwt.XFStyle() # Create Style
style.borders = borders # Add Borders to Style
worksheet.write(0, 0, 'Cell Contents', style)
workbook.save('Excel_Workbook.xls')

"""
爲單元格設置背景色:
"""
import xlwt
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('My Sheet')
pattern = xlwt.Pattern() # Create the Pattern
pattern.pattern = xlwt.Pattern.SOLID_PATTERN # May be: NO_PATTERN, SOLID_PATTERN, or 0x00 through 0x12
pattern.pattern_fore_colour = 5 # May be: 8 through 63. 0 = Black, 1 = White, 2 = Red, 3 = Green, 4 = Blue, 5 = Yellow, 6 = Magenta, 7 = Cyan, 16 = Maroon, 17 = Dark Green, 18 = Dark Blue, 19 = Dark Yellow , almost brown), 20 = Dark Magenta, 21 = Teal, 22 = Light Gray, 23 = Dark Gray, the list goes on...
style = xlwt.XFStyle() # Create the Pattern
style.pattern = pattern # Add Pattern to Style
worksheet.write(0, 0, 'Cell Contents', style)
workbook.save('Excel_Workbook.xls')

2、導出excel表(讀django字段數據)

  在django項目中實現用excel導出數據庫中數據。

一、添加導出excel路由 

  這裏是基於crm項目實現,在customer配置類中添加excel路由:

class CustomerConfig(ModelStark):
    """代碼省略"""
    def extra_url(self):
        """擴展路由"""
        temp = []
        temp.append(url(r"mycustomer/", self.mycustomer))
        temp.append(url(r'export/', self.excel_export))
        return temp

 

二、導出excel視圖函數

# 註冊客戶(學生)到stark
class CustomerConfig(ModelStark):
    """代碼省略"""

    def excel_export(self, request):
        """導出excel表格"""
        list_obj = models.Customer.objects.all().order_by("create_time")
        if list_obj:
            # 建立工做薄
            ws = Workbook(encoding="UTF-8")
            w = ws.add_sheet(u'數據報表第一頁')
            w.write(0, 0, 'id')
            w.write(0, 1, u'姓名')
            w.write(0, 2, u'性別')
            w.write(0, 3, u'民族')
            w.write(0, 4, u'籍貫')
            w.write(0, 5, u'身份證號')
            w.write(0, 6, u'通知書郵寄地址')
            w.write(0, 7, u'郵編')
            w.write(0, 8, u'聯繫電話')
            w.write(0, 9, u'聯繫電話2')
            w.write(0, 10, u'院校')
            w.write(0, 11, u'專業')
            w.write(0, 12, u'建立日期')
            w.write(0, 13, u'生源人')
            w.write(0, 14, u'備註')
            # 寫入數據
            excel_row = 1
            for obj in list_obj:
                data_id = obj.id
                data_name = obj.name
                # data_gender = obj.gender_choices  # 只顯示數字
                data_gender = obj.get_gender_display()
                data_nation = obj.nation
                data_birth = obj.birth_place
                data_identity_num = obj.identity_num
                data_address = obj.address
                data_postcode = obj.postcode
                data_tel = obj.tel
                data_tel2 = obj.tel_2
                data_school = obj.stu_school.title
                data_course = obj.course.first().name
                data_time = obj.create_time.strftime('%Y-%m-%d %H:%M:%S')
                data_consultant = obj.consultant.name
                data_memo = obj.memo
                w.write(excel_row, 0, data_id)
                w.write(excel_row, 1, data_name)
                w.write(excel_row, 2, data_gender)
                w.write(excel_row, 3, data_nation)
                w.write(excel_row, 4, data_birth)
                w.write(excel_row, 5, data_identity_num)
                w.write(excel_row, 6, data_address)
                w.write(excel_row, 7, data_postcode)
                w.write(excel_row, 8, data_tel)
                w.write(excel_row, 9, data_tel2)
                w.write(excel_row, 10, data_school)
                w.write(excel_row, 11, data_course)
                w.write(excel_row, 12, data_time)
                w.write(excel_row, 13, data_consultant)
                w.write(excel_row, 14, data_memo)
                excel_row += 1
                # 檢測文件是否存在
                # 方框中代碼是保存本地文件使用,如不須要請刪除該代碼
                ###########################
            exist_file = os.path.exists("stu_info.xls")
            if exist_file:
                os.remove(r"stu_info.xls")
            ws.save("customer_info.xls")
            ############################
            sio = BytesIO()
            ws.save(sio)
            sio.seek(0)
            response = HttpResponse(sio.getvalue(), content_type='application/vnd.ms-excel')
            response['Content-Disposition'] = 'attachment; filename=stu_info.xls'
            response.write(sio.getvalue())
            return response

 

(1)獲取日期並轉化格式

data_time = obj.create_time.strftime('%Y-%m-%d %H:%M:%S')

 

(2)獲取一對多對象名稱

data_consultant = obj.consultant.name

 

(3)獲取多對多對象名稱

data_course = obj.course.first().name

 

三、將註冊的模型類添加到字典_registry中

site.register(models.Customer, CustomerConfig)

 

3、導入excel表(插入django字段數據)

  導入時,一對多字段和多對多字段處理須要特別注意。

一、添加導入Excel路由

# 註冊客戶(學生)到stark
class CustomerConfig(ModelStark):
    def extra_url(self):
        """擴展路由"""
        temp = []
        temp.append(url(r"mycustomer/", self.mycustomer))
        temp.append(url(r'export/', self.excel_export))
        temp.append(url(r'import/', self.excel_import))
        return temp

 

二、導入Excel視圖函數

# 註冊客戶(學生)到stark
class CustomerConfig(ModelStark):
    """省略代碼"""
    def excel_import(self, request):
        """批量導入數據"""
        if request.method == 'GET':
            return render(request, 'excel_import.html', locals())
            # return JsonResponse({'msg': '不是post請求'})
        else:
            user_id = request.session.get("user_id")
            file_obj = request.FILES.get('my_file')
            type_excel = file_obj.name.split('.')[1]
            if 'xls' == type_excel:
                # 開始解析上傳的excel表格
                wb = xlrd.open_workbook(filename=None, file_contents=file_obj.read())
                table = wb.sheets()[0]
                nrows = table.nrows    # 行數
                # ncole = table.ncols  # 列數
                try:
                    # 正常的數據庫操做應該是原子性操做
                    with transaction.atomic():
                        for i in range(1, nrows):
                            # i/o
                            row_value = table.row_values(i)   # 一行的數據
                            # 添加多對多字段
                            # 主要這裏不能使用get,不然報錯:'Course' object is not iterable
                            course_obj = models.Course.objects.filter(name=row_value[9])
                            print(row_value[10], type(row_value[10]))  # 1002.0 <class 'float'>
                            consultant_obj = models.UserInfo.objects.get(code=str(int(row_value[10])))
                            # 生成學生對象,添加
                            customer_obj = models.Customer.objects.create(
                                name=row_value[0],
                                gender=row_value[1],
                                nation=row_value[2],
                                birth_place=row_value[3],
                                identity_num=row_value[4],
                                address=row_value[5],
                                postcode=row_value[6],
                                tel=row_value[7],
                                tel_2=row_value[8],
                                stu_school_id=1,
                                create_time=datetime.datetime.now(),
                                consultant=consultant_obj,    # 一對多字段
                                memo=row_value[11]
                            )
                            # create的時候不寫多對多字段,寫完後單獨設置便可
                            customer_obj.course.set(course_obj)
                except Exception as e:
                    return HttpResponse('出現錯誤...%s' % e)
                return HttpResponse("上傳成功")
            return HttpResponse('上傳文件格式不是xls')

(1)一對多字段

  consultant字段是一對多字段,使用以下方法添加:

consultant_obj = models.UserInfo.objects.get(code=str(int(row_value[10])))
# 生成學生對象,添加
customer_obj = models.Customer.objects.create(
    """代碼省略"""
    consultant=consultant_obj,    # 一對多字段
)

 

(2)多對多字段

  course字段是多對多字段,使用以下方法添加:

# 添加多對多字段
# 主要這裏不能使用get,不然報錯:'Course' object is not iterable
course_obj = models.Course.objects.filter(name=row_value[9])
print(row_value[10], type(row_value[10]))  # 1002.0 <class 'float'>
# 生成學生對象,添加
customer_obj = models.Customer.objects.create("""代碼省略""")
# create的時候不寫多對多字段,寫完後單獨設置便可
customer_obj.course.set(course_obj)
相關文章
相關標籤/搜索