ThinkGeo.com    |     Documentation    |     Premium Support

Creating New Shapefiles From Tables

I am running into an issue when I try to create shapefiles from a table.  We have tables set up that describe shapefile type, field names/types, and we are hard coding some default field lengths for those fields.  



I am running into problems with the end result.  The process below ends up creating .dbc, .dbf, .ids, .idx, .prj (copied through different means), .shp, and .shx files.  The shapefile opens up in our ThinkGeo application, but it doesn’t not open up in ArcMap.  Errors vary from saying that the shapes don’t match the records in the DBF to just a general cannot open the file error.  When I open the created shapefiles in qGIS, It seems to work, but there are extra fields appended to the attribute table.



Here is the code for this part:




01.Private Shared Sub ProcessShapefiles()
02.       'explanation of the items in the m_LayerFieldsToBeCreated dictionary
03.       'the keys are the names of the shapefiles… in my case, they are generic being layer1, layer2, layer3, etc…
04.       'the inner dictionary is as follows
05.       '–key = field/column name… ie. UNIQUEID, ID, GEOMETRY, Field1, Field2, etc… there may be 20-30 columns +/-
06.       'in the object(), there are 2 items… (0) = DbfColumnType…(1) = optional field length for character types
07. 
08.       'need to go through the dictionary to create new layer files
09.       For Each item As KeyValuePair(Of String, Dictionary(Of StringObject())) In m_LayerFieldsToBeCreated
10. 
11.           'create collection to hold the dbf columns
12.           Dim dbfColumns As New List(Of DbfColumn)
13. 
14.           'create the DBF columns
15.           For Each piece As KeyValuePair(Of StringObject()) In item.Value
16.               'create the new column
17.               Dim newColumn As DbfColumn = Nothing
18. 
19.               'set the properties of the new column
20.               Select Case DirectCast(piece.Value(0), DbfColumnType)
21.                   Case DbfColumnType.Character
22.                       newColumn = New DbfColumn(piece.Key, piece.Value(0), piece.Value(1), 0) 'in this case, piece.Value(0) = DbfColumnType.Character, piece.value(1) = a length (only as high as 254), no decimals for character
23.                   Case DbfColumnType.Float
24.                       newColumn = New DbfColumn(piece.Key, piece.Value(0), 13, 6)
25.                   Case DbfColumnType.Numeric
26.                       newColumn = New DbfColumn(piece.Key, piece.Value(0), 9, 0)
27.               End Select
28.                
29.               'making sure that something was created during the Select Case operation
30.               If newColumn IsNot Nothing Then
31.                   Debug.WriteLine(newColumn.ColumnName & " " & newColumn.ColumnType.ToString)
32.                   'populating a list of the new columns
33.                   dbfColumns.Add(newColumn)
34.               End If
35.           Next
36. 
37.           Try
38.               'create the shapefile
39.               'm_LayersToBeCreated is a dictionary where the key is the layer name and the value is the a ShapeFileType
40.               Debug.WriteLine(m_LayersToBeCreated.Item(item.Key).ToString & " " "." & item.Key & “.shp”)
41.                
42.               'create the shapefile - I tried this as a standard in case there were issues in my iteration, but it doesn’t work either
43.               'ShapeFileFeatureSource.CreateShapeFile(ShapeFileType.Point, "." & item.Key & “.shp”, dbfColumns, System.Text.Encoding.UTF8, OverwriteMode.Overwrite)
44.            
45.               'I have tried using iteration to generate a new shapefile that adjusts for what was in my table
46.               Select Case m_LayersToBeCreated.Item(item.Key)
47.                   Case ShapeFileType.Point
48.                       ShapeFileFeatureSource.CreateShapeFile(ShapeFileType.Point, "." & item.Key & “.shp”, dbfColumns, System.Text.Encoding.UTF8, OverwriteMode.Overwrite)
49.                   Case ShapeFileType.Polygon
50.                       ShapeFileFeatureSource.CreateShapeFile(ShapeFileType.Polygon, “." & item.Key & “.shp”, dbfColumns, System.Text.Encoding.UTF8, OverwriteMode.Overwrite)
51.                  Case ShapeFileType.Polyline
52.                       ShapeFileFeatureSource.CreateShapeFile(ShapeFileType.Polyline, “." & item.Key & “.shp”, dbfColumns, System.Text.Encoding.UTF8, OverwriteMode.Overwrite)
53.               End Select
54.                
55.               'thinking there might be an issue with the shapefile, I tried adding in an option to rebuild… still didn’t work
56.               'ShapeFileFeatureSource.Rebuild(item.Key & “.shp”)
57. 
58.                
59.               'assign the projection file— all the shapefiles to be created use the same projection that is assigned as a generic projection.prj file
60.               System.IO.File.Copy(”.\Projection.prj”, item.Key & “.prj”)
61. 
62.           Catch ex As Exception
63.               'need to specify down later
64.           End Try
65.       Next
66. 
67. 
68. 
69.   End Sub



For some reason, I am able to pull data from a spreadsheet and create a new shapefile from that.  I am including that code in here as well.  I don’t specifically see a big difference between the two methodologies so I don’t know where things are going wrong when reading the other way.  This one is doing pretty much the same thing except type checking the spreadsheet’s fields in order to determine the field type for the DbfColumn.





Here is the code for that part:




01.Private Sub ExportSpreadsheetToShapefile(ByVal sender As ObjectByVal As DoWorkEventArgs)
02. 
03.        Dim params() As Object = e.Argument
04. 
05.        Dim xColumnName As String = params(0)
06.        Dim yColumnName As String = params(1)
07.        Dim columnList As List(Of String) = params(2)
08.        Dim tableName As String = params(3)
09.        Dim shapefileText As String = params(4)
10. 
11.        'query the database to get the information
12.        ExportToShapefileSpreadsheet.GetSpreadsheetData(tableName, columnList)
13. 
14.        'construct the shapefile
15.        'create collection of datacolumns
16.        Dim dbfCollection As New List(Of DbfColumn)
17. 
18.        For As Integer = 0 To ExportToShapefileSpreadsheet.m_SelectedSpreadsheetData.Tables(“Table”).Columns.Count - 1 Step 1
19.            Dim item As DataColumn = ExportToShapefileSpreadsheet.m_SelectedSpreadsheetData.Tables(“Table”).Columns(i)
20.            ’ Dim newColumn As New DbfColumn(item.ColumnName, item.DataType.ToString, item.MaxLength)
21.            Dim newColumn As DbfColumn = Nothing
22.            Console.WriteLine(item.ColumnName & " " & item.DataType.ToString & " " & item.ColumnName.Length)
23. 
24.            'select the datatype based off the spreadsheet
25.            Select Case item.DataType
26. 
27.                Case GetType(Char), GetType(String)
28.                    newColumn = New DbfColumn(item.ColumnName.ToString.Trim(), DbfColumnType.Character, 254, 0)
29.                Case GetType(Date), GetType(DateTime)
30.                    newColumn = New DbfColumn(item.ColumnName.ToString.Trim, DbfColumnType.Date, 8, 0)
31.                Case GetType(Double), GetType(Single)
32.                    newColumn = New DbfColumn(item.ColumnName.ToString.Trim, DbfColumnType.Float, 13, 5)
33.                Case GetType(Integer)
34.                    newColumn = New DbfColumn(item.ColumnName.ToString.Trim, DbfColumnType.Numeric, 9, 0)
35.            End Select
36. 
37.            'add to the collection
38.            If newColumn IsNot Nothing Then
39.                dbfCollection.Add(newColumn)
40.            End If
41.        Next
42. 
43.        'create the shapefile----here this is only points though and I set the encoding-- in the previous example, I also tried setting the same encoding and overwriting but that didn’t work either.
44.        ShapeFileFeatureSource.CreateShapeFile(ShapeFileType.Point, shapefileText, dbfCollection, System.Text.Encoding.UTF8, OverwriteMode.Overwrite)
45.End Sub

My biggest issue is that the top code block ends up creating .dbc files and my .dbf isn’t configured properly.  When I try to open the .dbf in Excel, it is all jumbled and not in a tabular format.  I am not exactly sure why the second process works for this, but the top one doesn’t.



I have tried this on version 8.0 and 8.0.115.0.  Both do the same things with the top code.



Any advice would be great.  Thanks!


Here is an example of the shapefile that gets created.

001_Layer1.zip (1.66 KB)

Hi Brandon,



It looks you problem a little complex, so if I misunderstand any point please let me know.



I did a quickly test like this:






Dim newColumn As DbfColumn = Nothing



        newColumn = New DbfColumn(“Inv_TimeC”, DbfColumnType.Character, 254, 0)
        dbfColumns.Add(newColumn)



        newColumn = New DbfColumn(“12345678901”, DbfColumnType.Float, 13, 5)
        dbfColumns.Add(newColumn)



        newColumn = New DbfColumn(“Cha_c”, DbfColumnType.Numeric, 9, 0)
        dbfColumns.Add(newColumn)



        ShapeFileFeatureSource.CreateShapeFile(ShapeFileType.Point, “D:\eee.shp”, dbfColumns, System.Text.Encoding.UTF8, OverwriteMode.Overwrite)






It looks when our column name string is a little long, the dbc file will be auto generated.





And the pdf in excel looks strange now.





But when we limit the length of column name, the excel looks well.





So I think the two code haven’t different, just your data for the code is different, the column name is not the same.



You mentioned ArcMap don’t works but it looks qGIS works, does that because they don’t have the same solution for dbc? I think you can try to build a shape file with limited column name and test again.



Regards,



Don

Don… Thanks for the info.  I mistakenly used an underscore in two of my field names putting it at 11 characters.  I didn’t notice and thought there may be an exception or something thrown instead of generating the .dbc files.   
  
 I corrected the two field names and things look like they are generating properly.

Hi Brandon, 
  
 I am glad to hear your problem have been solved. 
  
 In fact I am not very sure about the requirement to generate dbc here, but I think that should be an enhancement for support long column name. 
  
 Any question please let us know. 
  
 Regards, 
  
 Don 


The version (8.0.300.0) or later versions of MapSuiteCore.dll writes DBFColumn names to a "DBC" format file. Are there any ways of avoiding writing data to "DBC" format files?

Hi Richard, 
  
 If the column length is bigger than 10, it will generate the DBC file.  
  
 Regards, 
  
 Don