1

我收到了 6 份每周 excel 报告,这些报告是我手动编译成一个非常大的月度报告的。每个报告有 5-30 列和 4000 到 130,000 行。

我正在整理一个简单的 Django 应用程序,它允许您上传每个报告,并且数据最终存储在数据库中。

这是我的models.py:

#UPEXCEL models
from django.db import models


############## LISTS ###############

class TransactionTypeList(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class TransactionAppTypeList(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class CrmCaseOriginList(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name



############## CLIENTS AND STAFF ###############

class Staff(models.Model):
    name = models.CharField(max_length=40)
    employee_id = models.CharField(max_length=40)
    start_date = models.TimeField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    first_name = models.CharField(blank=True, null=True, max_length=40)
    last_name = models.CharField(blank=True, null=True, max_length=40)
    email = models.EmailField(blank=True, null=True)
    phone = models.CharField(blank=True, null=True, max_length=20)
    street = models.CharField(blank=True, null=True, max_length=100)
    city = models.CharField(blank=True, null=True, max_length=100)
    state = models.CharField(blank=True, null=True, max_length=2)
    zipcode = models.CharField(blank=True, null=True, max_length=10)
    is_team_lead = models.BooleanField(default=False)
    boss = models.ForeignKey('Staff', related_name='Boss', null=True, blank=True)

    def __str__(self):
        return self.name

    class Meta:
        app_label="upexcel"


class Client(models.Model):
    name = models.CharField(max_length=40)
    short_name = models.CharField(max_length=20, blank=True, null=True)
    start_date = models.DateField(default=timezone.now, blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    team_lead = models.ForeignKey(Staff, related_name='client_team_lead')

    def __str__(self):
        return self.name

class ClientNameChart(models.Model):
    client_name = models.ForeignKey(Client, related_name='client_corrected_name')
    name_variation = models.CharField(max_length=100)
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '%s becomes %s' % (self.name_variation, self.client_name)

class StaffNameChart(models.Model):
    staff_name = models.ForeignKey(Staff, related_name='staff_corrected_name')
    name_variation = models.CharField(max_length=100)
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '%s becomes %s' % (self.name_variation, self.staff_name)



############## DATA FROM REPORTS ###############

class CrmNotes(models.Model):
    created_by = models.ForeignKey(Staff, related_name='note_creator')
    case_origin = models.CharField(max_length=20)
    client_regarding = models.ForeignKey(Client, related_name='note_client_regarding')
    created_on = models.DateTimeField()
    case_number = models.CharField(max_length=40)

class Transactions(models.Model):
    client_regarding = models.ForeignKey(Client, related_name='transaction_client')
    created_by = models.ForeignKey(Staff, related_name='transaction_creator')
    type = models.ForeignKey(TransactionTypeList, related_name='transaction_type')
    app_type = models.ForeignKey(TransactionAppTypeList, related_name='transaction_app_type')

    class Meta:
        app_label="upexcel"

class Timesheets(models.Model):
    staff = models.ForeignKey(Staff, related_name='staff_clocked_in')
    workdate = models.DateField()
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    total_hours = models.DecimalField(decimal_places=2, max_digits=8)

class Provider(models.Model):
    name = models.CharField(max_length=40)
    street = models.CharField(max_length=100)
    city = models.CharField(max_length=40)
    state = models.CharField(max_length=11)
    zip = models.CharField(max_length=10)

class StudentsApplication(models.Model):
    app_number = models.CharField(max_length=40)
    program = models.CharField(max_length=40)
    benefit_period = models.CharField(max_length=40)
    student_name = models.CharField(max_length=40)
    student_empl_id = models.CharField(max_length=40)
    requested_amount = models.DecimalField(max_digits=8, decimal_places=2)
    provider = models.ForeignKey(Provider, related_name='app_provider')
    provider_code = models.CharField(max_length=40)

class AuditReport(models.Model):
    was_audited = models.BooleanField(default=False)
    auditor = models.ForeignKey('upexcel.Staff', related_name='auditor')
    payment_defect = models.BooleanField(default=False)
    grant_discount_error = models.BooleanField(default=False)
    math_error = models.BooleanField(default=False)
    fees_book_error = models.BooleanField(default=False)
    other_error = models.BooleanField(default=False)
    overpayment_amount = models.DecimalField(max_digits=8, decimal_places=2)
    underpayment_amount = models.DecimalField(max_digits=8, decimal_places=2)
    doc_defect = models.BooleanField(default=False)
    status_change = models.BooleanField(default=False)
    admin_savings_defect = models.BooleanField(default=False)
    network_savings_defect = models.BooleanField(default=False)
    admin_adjustments = models.DecimalField(max_digits=8, decimal_places=2)
    network_adjustments = models.DecimalField(max_digits=8, decimal_places=2)
    error_corrected = models.BooleanField(default=False)
    comments = models.TextField(max_length=500)
    client = models.ForeignKey(Client, related_name='audited_client')
    staff = models.ForeignKey(Staff, related_name='processor_audited')
    application = models.ForeignKey(StudentsApplication, related_name='app_audited')

    class Meta:
        app_label="upexcel"

但是,我正在接受的 excel 报告需要对它们进行一些工作,并且我正在尝试弄清楚我应该如何处理它们并路由它们。

第一个挑战是每个报告都使用不同的数据引用相关的员工和客户。例如,如果 Staff.name 是“Bob Dole”,则一份报告将其命名为“Dole, Bob”。另一个有它作为“多尔,罗伯特”。还有一个是“Robert Dole”,然后是“103948210”,这是他的员工 ID 号。

此外,这些变化和新变化不断涌现,这就是我制作 ClientNameChart 和 StaffNameChart 的原因,用户可以在其中输入显示在报告中的字符串,并将其附加到 Client 或 Staff。然后在处理时,我们可以查找 StaffNameChart.name_variation,并返回相关的 StaffNameChart.Staff.employee_id,它应该可以很好地作为相应报告表中的外键(即 AuditReport.staff)

第二个挑战是获取一份报告,并将一些列路由到一个数据库表,而将其他列路由到另一个。例如,最大的是审计报告表。许多列只是直接转置到 AuditReport(models.Model) 中。但是,它也有每个 StudentApplication 和 Provider 的数据,我需要在其中获取几列,将它们作为新记录存储在目标表中,并将这些列替换为包含该目标表中该项目的外键的一列。

所以这就是我的追求。

这是我脑海中的操作顺序 - 我将使用最复杂的 Audit_Report_Wk_1.xlsx 报告来解决一次上传中的所有挑战:

  1. 上传文件
  2. 使用 openpyxl,加载只读数据:

    from openpyxl.worksheet.read_only import ReadOnlyWorksheet
    myexcelfile = request.FILES['file']
    myworkbook = load_workbook(myexcelfile, read_only=True)
    mysheet = myworkbook['Sheet1']
    
  3. 编写一个脚本,将员工、审计员和客户列的名称字符串与 匹配StaffNameChart.name_variation,并将其替换为StaffNameChart.Staff.name

  4. B 部分:如果客户或员工列是空白的,或者包含在姓名图表中找不到的字符串,则所有这些行都会保存在新的 Excel 文档中。编辑:我想我还可以创建一个名为的新模型类IncompleteAuditReport,它只有与每列匹配的字段并将其存储在那里,然后如果有人添加了新的 NameChart 变体,它可以触发快速查找以查看是否可以允许此过程完成并正确添加记录?)
  5. 检查mysheet将被外键替换的列ProviderStudentsApplication选项卡。如果它们各自的数据在各自的表中尚不存在,请添加新记录。无论哪种方式,然后用指向结果记录的外键替换它们的列。

这是正确的操作顺序吗?关于使用 openpyxl 等中的哪些特定工具以最有效的方式操作数据的任何建议,以便我可以使用尽可能少的资源来查找然后更改数十万个字段?

非常感谢你读到这里。我目前对更复杂的数据类型有点害怕,所以我不清楚将数据存储在内存中并在内存中进行操作的最佳方式。

4

0 回答 0