ThinkGeo.com    |     Documentation    |     Premium Support

Issue Building DBF File

Hi,


I'm trying to build a dbf file, but get an exception when I add a record.  I use the following code:


 



Collection<DbfMatchingPluginColumn> columns = new Collection<DbfMatchingPluginColumn>();
columns.Add(new DbfMatchingPluginColumn("Name", DbfMatchingPluginColumnType.String, 100));
columns.Add(new DbfMatchingPluginColumn("State", DbfMatchingPluginColumnType.String, 2));
columns.Add(new DbfMatchingPluginColumn("Lat", DbfMatchingPluginColumnType.Double, 12));
columns.Add(new DbfMatchingPluginColumn("Lon", DbfMatchingPluginColumnType.Double, 12));
DbfMatchingPlugin.CreateDbf(filename, columns);

DbfMatchingPlugin m = new DbfMatchingPlugin(filename, DbfMatchingPluginReadWriteMode.ReadWrite);
m.Open();

m.AddRecord(new object[] { name, state, lat, lon }); // Lat and lon are doubles


I get the following exception:
Input string was not in a correct format.

Looking at the stack trace, it is calling ParseInt32, however all my numbers are doubles, and all my columns are marked to be doubles.

Any help would be appreciated.

Thanks,

.Ryan.

Below is the full stack trace in case that helps 
  
    at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) 
    at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info) 
    at System.Int32.Parse(String s, IFormatProvider provider) 
    at ThinkGeo.MapSuite.MapSuiteGeocoder.xb55f028df11b563b.x046379d76270fa14(Object x7a8a4352af587677) 
    at ThinkGeo.MapSuite.MapSuiteGeocoder.xb55f028df11b563b.x51b5b098ad1b0b48(Int32 x7fa74eaed7729514, Object x7a8a4352af587677) 
    at ThinkGeo.MapSuite.MapSuiteGeocoder.xb55f028df11b563b.WriteRecordValue(Int32 recordIndex, Object[] values) 
    at ThinkGeo.MapSuite.MapSuiteGeocoder.x6ea8963987c68c6d.AddRecord(IEnumerable`1 recordValues) 
    at ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPlugin.AddRecord(IEnumerable`1 values) 
    at DbfMaker.Program.Main(String[] args) in

Ryan, 
  
   The DBF plugin has a special naming convention that needs to be followed.  Until now we have only used it internally to create the files we ship with.  I will gather the naming conventions and create a small document for you to explain how you need to build it. 
  
 David

Ryan, 
  
   I have a sample now showing how to do it but don’t have time to post it today.  Hold on one more day and everything will get posted by Friday.  Sorry for the wait. 
  
 David

 Ryan,


  Below is the code I promised.  We will post this as a code community project soon but before that I wanted to get you the source.  The key is that there are some certain fields that have to be in the DBF and they have some rules about them.


1. The first column needs to be prefixed with  'ID_' so in the example we use 'ID_Name' .  When you add the data to the DBF you must add the data sorted on this field from A-Z.  


2. For data int he DBF you want returned profix it with 'DT_' which stands for detail.  If a column does not have 'DT_' in front of it then it will not return in the search results.


3. There are 6 spatial fields we need at the end of the file.  They are BB_CX (Bounding Box Center X), BB_CY (Bounding Box Center X), BB_ULX (Bounding Box Upper Left Y), BB_ULY (Bounding Box Upper Left Y), BB_LRX (Bounding Box Lower Right X), BB_LRY (Bounding Box Lower Right Y).  These fields need to be in integer format.  You do this by multiplying the decimal degree value by 1,000,000 (See code example)


4. We use the above bounding box fields to zoom into the item found when we complete the search.


Let me know if you have any questions




using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Forms;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.MapSuiteGeocoder;

namespace BuildIndexFileFromShapeFile
{
    public partial class Sample : Form
    {
        // We use this to convert the decimal degree value, which is a double, to a integer to save 4 bytes
        private const int coordinatesMultiplier = 1000000;

        public Sample()
        {
            InitializeComponent();
        }

        private void btnBuildIndex_Click(object sender, EventArgs e)
        {
            // Here we create an empty DbfMatchPlugin with all of the columns
            DbfMatchingPlugin dbfMatchingPlugin = CreateEmptyDbfMatchingPlugin();

            // Here we load the shape file data, sort it and get it ready to add
            List<string> dataSource = PrepareData();

            // Here we add the sorted date to the DBFMatchPlugin
            PopulateDbfMatchPlugin(dataSource, dbfMatchingPlugin);

            MessageBox.Show("Build Index Completed", "Build Index File", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
        }

        private DbfMatchingPlugin CreateEmptyDbfMatchingPlugin()
        {
            // Here we create the column collection
            Collection<DbfMatchingPluginColumn> columns = new Collection<DbfMatchingPluginColumn>();

            // Note that the first field needs to have an 'ID_' prefix.  This also needs to be unique and sorted A-Z
            columns.Add(new DbfMatchingPluginColumn("ID_Name", ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPluginColumnType.String, 50));

            // The columns prefixed with 'DT_' are just detail columns.  They will be returned in the result but we 
            // ignore them from a program perspective
            columns.Add(new DbfMatchingPluginColumn("DT_FIPS", DbfMatchingPluginColumnType.String, 5));
            columns.Add(new DbfMatchingPluginColumn("DT_Pop", DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("DT_CuType", DbfMatchingPluginColumnType.String, 20));
            columns.Add(new DbfMatchingPluginColumn("DT_CuCode", DbfMatchingPluginColumnType.String, 10));
            columns.Add(new DbfMatchingPluginColumn("DT_Color", DbfMatchingPluginColumnType.String, 2));

            // The 'BB_CX' & 'BB_CY' stands for the bounding box center point X and Y
            // The 'BB_ULX' stand for the following..  Upper Left X, Upperl Left Y, Lower Right X and Lower Right Y
            // They are used by the geocoder to zoom into the selection once it is found
            columns.Add(new DbfMatchingPluginColumn("BB_CX", DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("BB_CY", DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("BB_ULX", DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("BB_ULY", DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("BB_LRX", DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("BB_LRY", DbfMatchingPluginColumnType.Long, 4));

            // This method creates the DBF based on the columns defines above
            DbfMatchingPlugin.CreateDbf(@"..\..\Data\Countries-PluginFormat.dbf", columns);

            // Here we just open the plugin we just created and pass it back out of the method
            DbfMatchingPlugin dbfMathingPlugin = new DbfMatchingPlugin(@"..\..\Data\Countries-PluginFormat.dbf", DbfMatchingPluginReadWriteMode.ReadWrite);
            dbfMathingPlugin.Open();

            return dbfMathingPlugin;
        }

        private List<string> PrepareData()
        {
            List<string> dataSource = new List<string>();

            // Build the index file incase it is not built
            ShapeFileFeatureLayer.BuildIndexFile(@"..\..\Data\cntry02.shp", BuildIndexMode.DoNotRebuild);

            // Open the shape file we will use to construct the match plugin
            ShapeFileFeatureLayer shapeFile = new ShapeFileFeatureLayer(@"..\..\Data\cntry02.shp");
            shapeFile.Open();

            // Get all the features from the shapefile with all the columns
            Collection<Feature> features = shapeFile.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns);

            // Loop through each feature and get the bounding box and add it to the datasource
            foreach (Feature feature in features)
            {
                // Calculate the boundingbox and center point then converts the doubles to int for storage in the DbfMatchPlugin
                RectangleShape boundingBox = feature.GetBoundingBox();

                // Center Point
                int centerX = Convert.ToInt32(Math.Round(boundingBox.GetCenterPoint().X, 6) * coordinatesMultiplier);
                int centerY = Convert.ToInt32(Math.Round(boundingBox.GetCenterPoint().Y, 6) * coordinatesMultiplier);

                // Bounding Box
                int ulPointX = Convert.ToInt32(Math.Round(boundingBox.UpperLeftPoint.X, 6) * coordinatesMultiplier);
                int ulPointY = Convert.ToInt32(Math.Round(boundingBox.UpperLeftPoint.Y, 6) * coordinatesMultiplier);
                int lrPointX = Convert.ToInt32(Math.Round(boundingBox.LowerRightPoint.X, 6) * coordinatesMultiplier);
                int lrPointY = Convert.ToInt32(Math.Round(boundingBox.LowerRightPoint.Y, 6) * coordinatesMultiplier);

                // Read this row into a string to be added to the data source.  We also add the bounding box
                // to the end of the row
                string sourceStr = string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}|{9}|{10}|{11}", feature.ColumnValues["CNTRY_NAME"], feature.ColumnValues["FIPS_CNTRY"], feature.ColumnValues["POP_CNTRY"], feature.ColumnValues["CURR_TYPE"], feature.ColumnValues["CURR_CODE"], feature.ColumnValues["COLOR_MAP"], centerX, centerY, ulPointX, ulPointY, lrPointX, lrPointY);

                // Add the data to the datasource
                dataSource.Add(sourceStr);
            }

            // Sort the data so that the country name is sorted from A-Z
            dataSource.Sort(delegate(string lineA, string lineB)
            { return string.Compare(lineA.Split('|')[0], lineB.Split('|')[0], StringComparison.OrdinalIgnoreCase); });

            return dataSource;
        }

        private void PopulateDbfMatchPlugin(List<string> dataSource, DbfMatchingPlugin dbfMatchingPlugin)
        {
            // Loop through all the data in the data source, which should already be sorted, and add it to
            // the DbfMatchPlugin
            foreach (string line in dataSource)
            {
                // Cast all of the data to the proper types
                string[] parts = line.Split('|');
                string cntryName = parts[0];
                string fips = parts[1];
                int pop = int.Parse(parts[2]);
                string currType = parts[3];
                string currCode = parts[4];
                string colorMap = parts[5];
                int centerX = int.Parse(parts[6]);
                int centerY = int.Parse(parts[7]);
                int ulPointX = int.Parse(parts[8]);
                int ulPointY = int.Parse(parts[9]);
                int lrPointX = int.Parse(parts[10]);
                int lrPointY = int.Parse(parts[11]);

                //  Add the record to the DbfMatchPlugin
                dbfMatchingPlugin.AddRecord(new object[] { cntryName, fips, pop, currType, currCode, colorMap, centerX, centerY, ulPointX, ulPointY, lrPointX, lrPointY });
            }

            dbfMatchingPlugin.Close();
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

    }
}


David



 When i was trying to build DBF file from my shape. In this line of code:


Collection<feature> features = layer.FeatureSource.GetAllFeatures( ReturningColumnsType.AllColumns);</feature>


i got this error:


We only Supported Charactor(C), Number(N), Logical(L), Date(D), Memo(M), Floating Point(F) now. You are using an UnSupported Format or your password is not right


what does this means?

and if there is a problem with my shapefile ,, how can i fix it?


please give me your advice quickly



Sara, 
  
 Thanks for your post and questions. 
  
 Could you send us the shape files you are testing against? If you want, you can upload it in the discussion form or send it to our support(support@thinkgeo.com) and asked to forward to Yale.  
  
 Thanks. 
  
 Yang 


Thanks Yang… 
  
 i successfully resolved the error 
  
 Sara

for reverse geocoding on data (not USA) 
 i have to build DBF file 
  
 my question is , what should be ID_ of the dbf file? (the city name or the city center location x&y) 
  
 when i made the city name is the ID_  and the center x&y are DT_ , i got only geocoding not reverse geocoding 
 Have i need to make the ID_ of the DBF for X and Y of the city?? 
  
 thanks, 
 Sara

 Sara,


 
Thanks for your posts, 
 
The ID_ field should be the key name value, I suggest you to use the ID_City as the key field name and please note after you create the index dbf file, please sort the records according to the ID_City field asc. 
 
Also about the geography information, you should use this prefix "BB_", for example:
 
Center point location:
 
Field name: BB_CX, BB_CY.
 
BoundingBox:
 
Field name: BB_ULX, BB_ULY, BB_LRX, BB_LRY.
 
If you are not sure about that please reference the following code when you creating your own dbf index file below:


columns.Add(new DbfMatchingPluginColumn("ID_City", ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPluginColumnType.String, 54));
            columns.Add(new DbfMatchingPluginColumn("DT_State", ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPluginColumnType.String, 2));
            columns.Add(new DbfMatchingPluginColumn("BB_CX", ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("BB_CY", ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("BB_ULX", ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("BB_ULY", ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("BB_LRX", ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPluginColumnType.Long, 4));
            columns.Add(new DbfMatchingPluginColumn("BB_LRY", ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPluginColumnType.Long, 4));
  If you still have any questions please let me know,


Thanks,


Scott,



Scott, 
  
 this code is what i already made … but still my location (lat, lng) doesn’t be matched 
 i need to send my shape file and the code to you  
 please provide me with an email to send them to you 
  
 Thanks, 
 Sara

Sara, 



You can contact ThinkGeo support to create a ticket so that we can track and resolve your problem smoothly, 



If you have any questions please let me know, 



Thanks, 



Scott,