DullCodes’s diary

programming,c++,python,MachineLearning,Math,Django,Competitive

Python で Excel をいじりたい

作るもの

英単語が入っているエクセルファイルをデータベースにいれて
4択的なアプリを作る

中身はこんな感じ

Meanings English Definition POS J Translation
afterward happening after something else happened adv その後
amongst in or through a group prep ~の間に;~の中の
artistic Being able to paint, write music, etc.; creative adj 芸術的な
backward toward what is behind you adv 後ろへ

英単語はいかに

www.newgeneralservicelist.org

New Academic Word List — New General Service List

Excelについて

Excelファイル には2つの拡張子が存在する

.xls : Microsoft Office 専用の独自規格 淘汰されつつある旧式の拡張子
.xlsx : 現在のエクセルファイルの統一規格的なもの こっちを使うのが普通
.xlsm : マクロが入っているエクセルファイルの規格

python で xlsx を使うための色々パッケージがあり
xlrd, openpyxl, pandas, xlwings が有名っぽいbr>

一番使うのが簡単そうな xlrd を使用する

xlrd

読むだけでいいのですごく簡単

# book を読み込み
wb_nawl = xlrd.open_workbook(nawl)

# シートを読み込み
sh_nawl = wb_nawl.sheet_by_index(0)

# シートの行数
for row in range(sh_nawl.nrows):
    # シートの列数
    for col in range(sh_nawl.ncols):
        # cell_value(行, 列) で表示
        print(sh_nawl.cell_value(row, col), end=' ')
    print()

こんな表示なる

Meanings English Definition POS J Translation 
afterward happening after something else happened adv その後 
amongst in or through a group prep ~の間に;~の中の 
artistic Being able to paint, write music, etc.; creative adj 芸術的な 
backward toward what is behind you adv 後ろへ 
bodily physically, as when lifting someone adv 身体の 
carrier a company, usually an airline, that carries things n 運送業;航空会社;電話会社 
collective formed by working together as a group adj 収集された; 集団の 

...

これを使えればOK

さっそくDjangoプロジェクトの適当なモデルに流し込んでいく

Django Project

適当につくる

Model

class WordModel(models.Model):
    class Meta:
        verbose_name = "wordmodel"
        verbose_name_plural = "wordmodels"

    meaning = models.CharField(max_length=100)
    definition = models.CharField(max_length=200)
    pos = models.CharField(max_length=20)
    translation = models.TextField()

    def __str__(self):
        return self.meaning

views

from django.shortcuts import render, redirect
from django.views import View
from .models import WordModel
import xlrd


class IndexView(View):
    def get(self, request, *args, **kwargs):
        ctx = {
            'words': WordModel.objects.all()
        }
        return render(request, 'read_excel/index.html', ctx)


class ExcelReader(View):
    def get(self, request, *args, **kwargs):
        self.insert_to_model()
        return redirect('read_excel:index')

    def insert_to_model(self):
        # save nawl
        dirname = 'static/words/'
        nawl = dirname + 'E-J+Definitions+from+NAWL+Builder+.xlsx'

        wb = xlrd.open_workbook(nawl)
        sheet = wb.sheet_by_index(0)

        # 一行目は列名 なので飛ばす
        for row in range(sheet.nrows, start=1):
            WordModel.objects.create(
                meaning=sheet.cell_value(row, 0),
                definition=sheet.cell_value(row, 1),
                pos=sheet.cell_value(row, 2),
                translation=sheet.cell_value(row, 3)
            )

sqliteを使っているからか、1000 * 4 くらいの
エクセルなんだけど結構時間がかかる(1分くらい)
入ったかどうか確認

{% extends "base.html" %}

{% block main %}
<main>
    <h1>Main</h1>

    <div>
        <p>Hello World</p>
        <table>
            <tr>
                <th>Meaning</th>
                <th>Definition</th>
                <th>POS</th>
                <th>Translation</th>
            </tr>

            {% for word in words %}
            <tr>
                <td>{{word.meaning}}</td>
                <td>{{word.definition}}</td>
                <td>{{word.pos}}</td>
                <td>{{word.translation}}</td>
            </tr>
            {% endfor %}
        </table>
    </div>
</main>
{% endblock %}

f:id:DullCodes:20200402015154p:plain
excel to db from excel

Quiz

四択みたいのにしたかったけど面倒なのでただランダムに表示するだけにする

class QuizView(View):
    def get(self, request, *args, **kwargs):
        # order_by('?') でランダムに並び替える
        # import random から sample などでもいいかな
        word = WordModel.objects.order_by('?')[0]
        ctx = {'word': word}
        return render(request, 'read_excel/quiz.html', ctx)

template も超カンタンに

{% extends 'base.html' %}

{% block main %}
<main>
  <h2>Quiz</h2>

  <p>[{{ word.pos }}] {{ word.meaning }}</p>
  <p>{{ word.definition }}</p>
  <p>{{ word.translation }}</p>
</main>
{% endblock main %}

4択にするんだったら、モデルを適当に4つ取得して
一番上に英単語を表示、下に和訳を4つ表示
みたいな感じにすればいいかも

逆にすれば 和英の4択もできるかも

まとめ

Python では csv, excel ともに簡単にいじれますね