PyQt5のQTableWidgetへDBから出力 ＋ csvへ保存



会社の業務で作ったので、共有します。
重要なのは以下の2点。後は飾りです。

1：データベースから出力したデータをテーブルへ入れる（create_table）
2：保存ボタンでcsvへ保存(save_csv)

sql文とDBは、各自お願いします。



```tableCSV.py
import sys
import psycopg2
from PyQt5.QtWidgets import QWidget, QTableWidget, QTableWidgetItem, \
    QVBoxLayout, QPushButton, QHBoxLayout, QFileDialog, QApplication
import csv


class App(QWidget):

    def __init__(self):
        super().__init__()

        self.ex_list = []

        self.title = 'タイトル'
        self.left = 300
        self.top = 200
        self.width = 300
        self.height = 400
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.tableWidget = QTableWidget()
        self.horHeaders = ['項目1', '項目2', '項目3']
        self.create_table()

        btn_save = QPushButton('保存', self)
        btn_save.clicked.connect(self.save_csv)

        # btnを右側に寄せる
        hbox = QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(btn_save)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.tableWidget)
        self.layout.addItem(hbox)
        self.setLayout(self.layout)

        self.show()

    def create_table(self):
        self.tableWidget.setColumnCount(len(self.horHeaders))
        self.tableWidget.setHorizontalHeaderLabels(self.horHeaders)

        sql = ""

        data = fetch_db(sql)
        self.tableWidget.setRowCount(len(data))

        # テーブルにデータを挿入
        for (i, record) in enumerate(data):
            for (j, cell) in enumerate(record):
                self.tableWidget.setItem(i, j, QTableWidgetItem(str(cell)))

        # テーブルの大きさを項目に合わせる
        self.tableWidget.resizeRowsToContents()
        self.tableWidget.resizeColumnsToContents()

    # 保存処理→CSVで保存
    def save_csv(self):
        # 「名前をつけて保存」を開く
        file_name, filters = QFileDialog.getSaveFileName(filter="CSV files (*.csv)")
        # 保存ボタン押した後の処理
        if file_name != '':
            with open(file_name, 'wt') as stream:
                writer = csv.writer(stream, lineterminator='\n')
                writer.writerow(self.horHeaders)
                for row in range(self.tableWidget.rowCount()):
                    row_data = []
                    for column in range(self.tableWidget.columnCount()):
                        item = self.tableWidget.item(row, column).text()
                        row_data.append(item)
                    writer.writerow(row_data)


def fetch_db(sql):

    # postgreSQLへアクセスするための情報
    access_info = ["DB", "192.168.0.1", "USER", "8080", "PASS"]
    conn: psycopg2

    try:
        conn = psycopg2.connect(database=access_info[0], host=access_info[1], user=access_info[2],
                                port=access_info[3], password=access_info[4])
        cur = conn.cursor()
        cur.execute(sql)
        conn.commit()
        return cur.fetchall()

    except psycopg2.OperationalError as e:
        print('Unable to connect!\n{0}').format(e)
        sys.exit(1)
    finally:
        if conn:
            conn.close()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())
```

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/103457/1d4bc4dc-94d2-71ae-9b9b-5f4fa1f53117.png)