1. 程式人生 > >【Django Series - 05】基於 "xlsxwriter + BytesIO"(Python3)生成 Excel 報表 ||| Python2 StringIO.StringIO()

【Django Series - 05】基於 "xlsxwriter + BytesIO"(Python3)生成 Excel 報表 ||| Python2 StringIO.StringIO()

Django Series(Django2.1.2 + Anaconda3)

(一)安裝並配置 Django 環境 ||| 基於 Django 進行 Web 開發

(二)Django 基礎知識:語法、教程

(三)使用者管理模組:建立使用者、登入、退出

(四)資料的增刪改:使用者提交資料,驗證資料的有效性並傳輸至後臺(jQuery.post、jQuery.getJSON)

(五)基於 "xlsxwriter  + BytesIO"(Python3)生成 Excel 報表 ||| Python2 StringIO.StringIO()


說明:本系列教程根據最近實踐過程進行整理、總結和分享。由於時間和精力有限,發表時內容分析部分可能不是很完整

,後續有時間會慢慢補充。同時!!也希望感興趣的同學可以提出一些細節問題和建議,我會根據這些問題進一步整理和完善哈。

更新日誌:

20181019:發表第一版,主要以程式碼分享為主;知識點分析較為粗略。


知識點分析:

 

 

實現程式碼:

Python3 + Django2.1.2

views.py

## 匯出excel報表
@csrf_exempt
def Cur_ProjectsReport(request):

	try:
		import xlsxwriter
		output = BytesIO()
		workbook = xlsxwriter.Workbook(output)

		target_sheet1 = workbook.add_worksheet(u"XXXX現有專案情況")
		target_sheet1.merge_range(0, 0, 0, 0+10, u"XXXX現有專案情況報表")
		## title
		target_sheet1.write(1, 0, u"工作令號")
		target_sheet1.write(1, 1, u"專案名稱")
		target_sheet1.write(1, 2, u"是否結項")
		target_sheet1.write(1, 3, u"合同日期")
		target_sheet1.write(1, 4, u"合同金額")

		## table
		projects_list = Cur_Projects.objects.all()
		i = 2
		for project in projects_list:
			target_sheet1.write(i, 0, u"{}".format(project.proj_id))
			target_sheet1.write(i, 1, u"{}".format(project.proj_name))
			target_sheet1.write(i, 2, u"{}".format(project.progress))
			target_sheet1.write(i, 3, u"{}".format(project.contract_date.strftime("%Y%m%d")))
			target_sheet1.write(i, 4, u"{}".format(project.contract_cost))

			i += 1

		date_day = datetime.datetime.now().strftime('%Y%m%d')
		file_name = "ProjectReport{}_{}.xlsx".format(date_day, request.session.get("UserName"))

		workbook.close()
		xlsx_data = output.getvalue()
		response = HttpResponse(content_type='application/ms-excel')
		response['Content-Disposition'] = 'attachment; filename=%s' % file_name
		response.write(xlsx_data)

		hcq_write(request.session.get('log_file_path'), True, True, "[{}({})]【成功】匯出現有專案報表:{}".format(
										request.session.get('UserName'), request.session.get('RoleTypeID'), file_name))

		return response

	except Exception as e:
		hcq_write(request.session.get('log_file_path'), True, True, "[{}({})]【異常】匯出現有專案報表:{}".format(
										request.session.get('UserName'), request.session.get('RoleTypeID'), e))
		response = HttpResponse()
		response.write("failure")
		return response

xxx.html

<a class="btn btn-default" type="button" href="{% url 'app_ManageSystem:Cur_ProjectsReport' %}">生成報表</a>

Python2 + Django1.6.11

Python2 直接 imort StringIO 模組,呼叫 StringIO.StringIO()。但 Python3 已經對 StringIO 模型進行修改,如下方法在Python2能夠成功匯出excel報表,但在Python3環境下會報錯。

## 專案出貨:匯出excel報表
@csrf_exempt
def ProjectSaleReport(request, proj_id):
	import xlwt
	import StringIO

	print("proj_id = {}".format(proj_id))

	try:
		## 獲取內容
		if Proj_info.objects.filter(proj_id = proj_id).exists():
			proj_name = Proj_info.objects.get(proj_id = proj_id).proj_name
		else:
			proj_name = "沒有獲取到專案名稱"

		ProjectSale_list = ProjectSale_info.objects.filter(proj_id = proj_id).order_by("-sale_goods_type")
		date_day = datetime.datetime.now().strftime('%Y%m%d')

		## 寫入 excel
		ws = xlwt.Workbook(encoding='utf-8')
		target_sheet = ws.add_sheet(u"{}專案出貨報表".format(proj_name))


		'''
		- 合併單元格
		write_merge(x, x + h, y, w + y, string, sytle)
		x表示行,y表示列,w表示跨列個數,h表示跨行個數,string表示要寫入的單元格內容,style表示單元格樣式
		注意,x,y,w,h,都是以0開始計算的
		'''
		target_sheet.write_merge(0, 0, 0, 0+4, u"工程名稱:{}".format(proj_name))
		target_sheet.write_merge(0, 0, 7, 7+2, u"出貨編號:{}".format(proj_id))
		target_sheet.write_merge(1, 1+0, 7, 7+2, u"匯出日期:{}".format(date_day))

		## title
		target_sheet.write(2, 0, u"序號")
		target_sheet.write(2, 1, u"收費專案")
		target_sheet.write(2, 2, u"品名")
		target_sheet.write(2, 3, u"單位")
		target_sheet.write(2, 4, u"數量")
		target_sheet.write(2, 5, u"人工費單價")
		target_sheet.write(2, 6, u"人工費總價")
		target_sheet.write(2, 7, u"報價")
		target_sheet.write(2, 8, u"收入金額(元)")
		target_sheet.write(2, 9, u"備註")

		## write content
		index = 1
		i = 3
		for ProjectSale in ProjectSale_list:

			target_sheet.write(i, 0, u"{}".format(index))
			target_sheet.write(i, 1, u"{}".format(ProjectSale.sale_goods_type))
			target_sheet.write(i, 2, u"{}".format(ProjectSale.sale_goods_name))
			target_sheet.write(i, 3, u"{}".format(ProjectSale.sale_unit))
			target_sheet.write(i, 4, u"{}".format(ProjectSale.sale_number))
			target_sheet.write(i, 5, u"{}".format(ProjectSale.staff_unit_price))
			target_sheet.write(i, 6, u"{}".format(ProjectSale.staff_cost))
			target_sheet.write(i, 7, u"{}".format(ProjectSale.sale_unit_price))
			target_sheet.write(i, 8, u"{}".format(ProjectSale.sale_income))
			target_sheet.write(i, 9, u"{}".format(ProjectSale.note))
			i += 1
			index += 1

		file_name = proj_name + "_" + date_day + ".xls"
		file_path = "./report/" + file_name
		print(file_path)
		if os.path.exists(file_path):
			os.remove(file_path)
		ws.save(file_path)
		sio = StringIO.StringIO()
		ws.save(sio)
		sio.seek(0)

		response = HttpResponse(sio.getvalue(), content_type='text/html')
		response['Content-Disposition'] = 'attachment; filename=' + file_name.encode('GBK')
		response.write(sio.getvalue())

		print("[successful]: ProjectSaleReport")
		return response

	except Exception as e:
		print("[failure]: ProjectSaleReport - {}".format(e))
		response = HttpResponse()
		response.write("failure")
		return response

 


重要參考文獻: