Search code examples
pythonfoxprodbf

How can i save field types and field sizes after working in dbf library in Python?


I work with fox pro dbf files in dbf library in Python. I faced one problem. I have in my dbf file field 'DISTANCE' with field 'type-Double, width - 8, decimal - 3' in VisualFoxPro. After creating table in dbf library in Python, 'DISTANCE' field type is 'B binary' after adding two columns, filling them with data and closing dbf in Python i get 'DISTANCE' with field 'type-Double, width - 8, decimal - 0' in VisualFoxPro. Could you explain why it happens and how can i fix it?

Here is my code:

import dbf

rs_refr = dbf.Table('rs_refr.dbf', codepage = 'cp1252', ignore_memos = True)
rs_refr.open(dbf.READ_WRITE)

rs_refr.add_fields('UT_WT N(5,2)')
rs_refr.add_fields('WT_UT N(5,2)')

for record in rs_refr:
    wt = record['WT']
    with record as r:
        r['UT_WT'] = wt
        r['WT_UT'] = wt

db.close()

I tried to create new dbf file and fill it with data from original dbf file but i got the same result as after a.m. code. 'DISTANCE' still was 'type-Double, width - 8, decimal - 0' in VisualFoxPro.

I expect to get 'DISTANCE' with field 'type-Double, width - 8, decimal - 3' after program was rus.


Solution

  • The number of decimal places in the Double field in VFP is for display only and has no effect on the precision of the data saved, the dbf module in python does not support that decimal value indication in the Double field definition so when the structure of the table is changed in python it automatically removes that value without affecting the saved value in the table. If you try the following in Visual FoxPro to create the rs_refr table with the distance field as (Double, width 8, decimal 3):

    CREATE TABLE rs_refr (distance B(3))
    INSERT INTO rs_refr (distance) VALUES (1234.123)
    ? rs_refr.distance && Displays 1234.123
    USE
    

    And then run your Python program that changes the table structure by adding two fields:

    import dbf
    
    rs_refr = dbf.Table('rs_refr.dbf', codepage = 'cp1252', ignore_memos = True)
    rs_refr.open(dbf.READ_WRITE)
    
    rs_refr.add_fields('UT_WT N(5,2)')
    rs_refr.add_fields('WT_UT N(5,2)')
    
    rs_refr.close()
    

    If you go back to the table structure in Visual FoxPro you will find the Distance field type changed to be (Double, width 8, decimal 0) while the saved data is not touched, to check that test the following code:

    USE rs_refr
    ? rs_refr.distance && Displays 1234
    ? EVALUATE("rs_refr.distance") = 1234 && Displays .F.
    ? EVALUATE("rs_refr.distance") = 1234.123 && Displays .T.
    

    So the data is not touched and is the same as before the structure was changed by Python.