1
votes

Transférer des données de la feuille de calcul Excel (openpyxl) vers la table de base de données (dbf)

J'ai un simple problème de lecture d'une feuille de calcul Excel, de traiter chaque ligne contenant environ 83 colonnes comme un enregistrement de base de données unique, de l'ajouter à l'enregistrement de datum local et finalement d'ajouter et d'écrire sur le fichier DBF.

Je peux extraire toutes les valeurs d'Excel et ajoutez-les à la liste. Mais la liste n'est pas une syntaxe correcte et je ne sais pas comment préparer / convertir la liste en enregistrement de base de données. J'utilise Openpyxl, dbf et python 3.7.

Pour le moment, je ne fais que tester et essayer de préparer les données pour la ligne 3 (d'où min_max lignes = 3)

Je comprends que les données doivent être au format (('', '', '', ... 83 entrées), \ ('', '', '', ... 83 entrées) \ )

Mais je ne sais pas comment convertir les données de la liste en enregistrement ou, alternativement, comment lire des données Excel directement dans un format DF appendable

raise TypeError("data to append must be a tuple, dict, record, or template; not a %r" % type(data))
TypeError: data to append must be a tuple, dict, record, or template; not a <class 'list'>

L'erreur se plaint de l'utilisation de la liste à ajouter à la table, et cela devrait être un enregistrement, etc. . Veuillez expliquer comment je peux convertir des lignes Excel en données de table DBF pouvant être ajoutées.

tbl_tst.open(mode=dbf.READ_WRITE) # all fields character string

for everyrow in ws_IntMstDBF.iter_rows(min_row = 3, max_row = 3, max_col = ws_IntMstDBF.max_column-1):
    datum = [] #set([83]), will defining datum as () help solve the problem?
    for idx, cells in enumerate(everyrow):
        if cells.value is None: # for None entries, enter empty string
            datum.append("")
            continue
        datum.append(cells.value) # else enter cell values 

     tbl_tst.append(datum) # append that record to table !!! list is not record error here

tbl_tst.close()


0 commentaires

3 Réponses :



1
votes

Changez

tbl_tst.append(tuple(datum))

vers

tbl_tst.append(datum)

et cela éliminera cette erreur. Tant que toutes les données de votre cellule ont le type approprié, l'ajout devrait fonctionner.


2 commentaires

Salut Ethan, j'ai utilisé votre suggestion et j'ai pu écrire les DBF sans problème. Le bonus supplémentaire était le fait que pyinstaller exe est entièrement fonctionnel alors que dans ma solution, pysal donnait une erreur dans l'exe généré. J'ai un problème en attente avec l'exe que les chemins relatifs tels que .. \ input \ file, etc. fonctionnent bien à partir du dossier exe mais les chemins absolus ne fonctionnent pas à moins que je ne déplace le fichier exe vers le dossier src. Est-ce une question pour un nouveau fil?


@MakJ: Oui, veuillez poser une nouvelle question pour cela. Heureux que cela fonctionne pour vous maintenant!



0
votes

Merci pour les réponses, je suis allé sur un peu de tangente depuis hier soir en essayant différentes solutions.

Une solution qui a fonctionné pour moi est la suivante: Je me suis assuré que les données de la feuille de calcul que j'utilise sont toutes des chaînes / texte et j'ai converti toutes les entrées nulles en type de chaîne et saisi une chaîne vide. Donc, le code suivant effectue cette tâche:

import pandas as pd
import pysal as ps
import numpy as np

# code from function df2dbf
else:
    type2spec = {int: ('N', 20, 0),
                 np.int64: ('N', 20, 0),
                 float: ('N', 36, 15),
                 np.float64: ('N', 36, 15),
                 str: ('C', 200, 0)
                 }
    #types = [type(df[i].iloc[0]) for i in df.columns]
    types = [type('C') for i in range(0, len(df.columns))] #84)] #df.columns)] #range(0,84)] # i not required, to be removed
    specs = [type2spec[t] for t in types]
db = ps.open(dbf_path, 'w')
# code continues from function df2dbf

Après avoir écrit la feuille de calcul, je l'ai rouverte à l'aide de panda dataframe et vérifié si le contenu était de type chaîne et qu'il n'y avait pas de "nan" valeurs restantes dans la trame de données. Ensuite, j'ai utilisé la fonction df2dbf de "Dani Arribas-Bel", je l'ai modifiée pour l'adapter aux données avec lesquelles je travaille et je l'ai convertie en dbf.

Le code qui importe le dataframe et le convertit au format dbf est le suivant:

abspath = Path(__file__).resolve() # resolve to relative path to absolute
rootpath = abspath.parents[3] # root (my source file is3 sub directories deep
xlspath = rootpath / 'sub-dir1' / 'sub-dir2' / 'sub-dir3' / 'test.xlsx'
# above code is only resolving file location, ignore 
pd_Mst_df = pd.read_excel(xlspath)
#print(pd_Mst_df) # for debug 
print("... Writing Master DBF file ")
df2dbf(pd_Mst_df, dbfpath) # dbf path is defined similar to pd_Mst path

La fonction df2dbg utilise pysal pour écrire des dataframe au format dbf: J'ai apporté quelques modifications au code pour détecter la longueur de la ligne et les types de caractères comme suit:

#house keeping
for eachrow in ws_IntMstDBF.iter_rows(min_row=2, max_row=ws_IntMstDBF.max_row, max_col=ws_IntMstDBF.max_column):
    for idx, cells in enumerate(eachrow):
        if cells.value is None: # change every Null cell type to String and put 0x20 (space)
            cells.data_type = 's'
            cells.value = " "

Le cadre de données Pandas n'a pas nécessité de modifications supplémentaires car toutes les données source étaient correctement formatées auparavant étant engagé dans un fichier Excel.

Je fournirai le lien vers pysal et df2dbf dès que je le trouverai sur stackoverflow.


0 commentaires