How to Build an Online Database APP by Python, PySide6 and Google Sheets (6): Edit Account

Henry Wu
4 min readDec 26, 2023

--

Previously

This article is about how to “edit account” in the app:

Previously

Call function in the Main Window

  1. display_edit_account_form (in MainWindow Class):
  • Clears existing content in the main window.
  • Opens a dialog (SelectAccountDialog) to select an account for editing.
  • If an account is selected, fetches its data and displays the form for editing account details using showEditAccountForm.
class MainWindow(QMainWindow):
def display_edit_account_form(self):
# Clear existing content
self.clear_content()

# Open the dialog to select an investor
dialog = SelectAccountDialog(self.google_sheets_client)
result = dialog.exec()

if result == QDialog.Accepted:
selected_id = dialog.getSelectedAccountID()
if selected_id:
account_data = self.fetch_edit_account_data(selected_id)

if account_data:
self.showEditAccountForm(account_data)

2. fetch_edit_account_data (in MainWindow Class):

  • Connects to the Google Sheets worksheet named “02_Accounts”.
  • Maps column names to indices and verifies the presence of required columns.
  • Searches for the specified account by its ID and retrieves its row data.
  • Constructs and returns a dictionary with the account’s data, including related investor information.
    def fetch_edit_account_data(self, account_id):
# Connect to Google Sheets and select the appropriate worksheet
worksheet = self.google_sheets_client.open_spreadsheet(GOOGLESHEET_ID).worksheet("02_Accounts")

# Get the header row (first row) to map column names to their indices
header_row = worksheet.row_values(1)
column_index_map = {name: index for index, name in enumerate(header_row)}

# Ensure all required columns are present
required_columns = ["ID_Account", "ID_Investor", "Type", "Last Name", "First Name", "Company Name"]
for column in required_columns:
if column not in column_index_map:
print(f"Column '{column}' not found in the worksheet.")
return None

# Get all values in the 'Account ID' column
account_id_column = worksheet.col_values(column_index_map["ID_Account"] + 1)

# Find the row index for the matching account_id
try:
row_index = account_id_column.index(account_id) + 1 # +1 because spreadsheet indices start at 1
except ValueError:
# Account ID not found
return None

# Fetch only the row with the matching Account ID
row_data = worksheet.row_values(row_index)

# Construct account data ensuring all keys exist in column_index_map and row_data
account_data = {}
for key, index in column_index_map.items():
if index < len(row_data):
account_data[key] = row_data[index]
else:
account_data[key] = "N/A"

# Fetch the investor data associated with this account
investor_id = account_data.get("ID_Investor")
if investor_id:
investor_data = self.fetch_investor_data(investor_id)
account_data["investor_data"] = investor_data

return account_data

3. showEditAccountForm (in MainWindow Class):

  • Creates an instance of EditAccountForm using the fetched account data.
  • Adds the edit form widget to the main window’s layout.
    def showEditAccountForm(self, account_data):
# Create the EditAccountForm with the fetched account data
edit_account_form = EditAccountForm(self.google_sheets_client, account_data)
self.content.layout().addWidget(edit_account_form)

Create Edit Account Class

EditAccountForm Class inherits from AddAccountForm.

  • __init__: Initializes the form using the super class constructor with investor data and populates it with the existing account data.
class EditAccountForm(AddAccountForm):
def __init__(self, google_sheets_client, account_data):
# Call the super class constructor with investor data
super().__init__(google_sheets_client, account_data["investor_data"])

# Populate the form with existing account data
self.populate_form(account_data)
  • populate_form: Fills in the form fields with the account data. It ensures that certain fields like 'Reinvest/Cash Dividend' and 'Account ID' are set correctly and made uneditable.
    def populate_form(self, account_data):
# Populate the account fields
for field, widget in self.input_fields.items():
if field in account_data:
if isinstance(widget, QLineEdit):
widget.setText(account_data[field])
elif isinstance(widget, QComboBox):
index = widget.findText(account_data[field])
widget.setCurrentIndex(index)

# Special handling for 'Reinvest/Cash Dividend' QComboBox
reinvest_cash_dividend_widget = self.account_id_fields.get("Reinvest/Cash Dividend")
if reinvest_cash_dividend_widget:
reinvest_cash_dividend_widget.setEnabled(False)
reinvest_cash_dividend_widget.setStyleSheet("background-color: lightgrey;")

# Set Account ID as uneditable
self.account_id_fields["Account ID"].setText(account_data["ID_Account"])
self.account_id_fields["Account ID"].setReadOnly(True)
self.account_id_fields["Account ID"].setStyleSheet("background-color: lightgrey;")

self.account_data = account_data
  • submit_form: Collects updated data from the form, updates the Google Sheets database, and handles success or error messages.
    def submit_form(self):
# Collect updated data from input fields
updated_data = {}
for field_name, widget in self.input_fields.items():
if isinstance(widget, QLineEdit):
updated_data[field_name] = widget.text()
elif isinstance(widget, QComboBox):
updated_data[field_name] = widget.currentText()

self.account_data.update(updated_data)
updated_data = self.account_data

try:
# Update the existing account data in Google Sheets
self.update_account_data_in_sheet(updated_data)

QMessageBox.information(self, "Success", "Account data updated successfully.")
except Exception as e:
QMessageBox.critical(self, "Error", f"Failed to update account data: {e}")

# Clear the input fields after submission
self.clear_input_fields()
  • update_account_data_in_sheet: Updates the existing account data in the Google Sheets worksheet "02_Accounts" by finding the correct row and updating it with the new data.
    def update_account_data_in_sheet(self, updated_data):
try:
worksheet = self.google_sheets_client.open_spreadsheet(GOOGLESHEET_ID).worksheet("02_Accounts")
data = worksheet.get_all_values()
headers = data[0]
id_column_index = headers.index("ID_Account") + 1 # +1 for 1-based index in Google Sheets

# Find the row of the account to update
row_to_update = None
for i, row in enumerate(data):
if row[id_column_index - 1] == updated_data["ID_Account"]: # -1 for 0-based index in Python
row_to_update = i + 1 # +1 for 1-based index in Google Sheets
break

if row_to_update is None:
raise Exception("Account ID not found in the sheet.")

# Prepare the updated row data
updated_row = [updated_data.get(header, "") for header in headers]

# Update the row in the sheet
worksheet.update(f"A{row_to_update}:{chr(64 + len(headers))}{row_to_update}", [updated_row])
except Exception as e:
raise Exception(f"Error updating account data: {e}")

--

--

Henry Wu
Henry Wu

Written by Henry Wu

Indie Developer/ Business Analyst/ Python/ AI/ Former Journalist/ Codewriter & Copywriter