Up to now, I has worked with mapinfo. I have a big vector layer (points) with a complex symbology.

For several days, I gave up mainfo for qgis. Is there a way to converting my mapinfo files (.tab) toward a file format supported by qgis. of course, i would like saving the symbology (styling) during the file conversion.

I would like convert a big point layer from .Tab toward .SHP and saving the style into Qgis. The symbology of my layer is quite complexe (variables of coulours, shape, symbols). I'm working with a windows 7 32 bits. Mapinfo 12.0 and qgis 2.6 are installed.

I downloaded the plugin from this following repository :


I opened the prompt command OsGeo4W shell available with my qgis 2.6.

I tried to execute the plugin. I received an error message. This message seems to be dealing with a fied which must be supplied (with -c argument) but i don't understand.

Which column must be supplied?

The current structure of my command is : python mapinfoToQgis.py pathINPUT.Tab pathOUTPUT.qml --UseMapInfo

I paste two screen shots :

A. focus on my .Tab mapinfo POINT layer with complex symbology enter image description here

B. error mesage via prompt command enter image description here

Could you throw light for me?


If the styling of elements is thematic (and you know what columns drive the theme) you can build a QML file programmatically in PostgreSQL.

For example, I have a file with ~150 styles for government zone polygons (subsets of the zones have the same style). The data was originally in MapInfo format in two TAB files - one with the zone polygons, another with aspatial data like zone_code, description, group, and lastly 'red', 'green' 'blue' (the last 3 are the RGB values for the recommended colour ramp).

To create my QML file, I did the following:

(1) import the data into PostgreSQL (using ogr2ogr);
(2) write a python script that looks like this -

import psycopg2

# Set up connection to database
conn_string = "host='localhost' dbname='[db]' user='[me]' password='[not telling]'"

# Connect to database
conn = psycopg2.connect(conn_string)

# set up default cursor (to run queries)
cursor = conn.cursor()

# Get LGA details; store them to a list
xmlelement(name qgis, 
xmlattributes(\'2.8.2-Wien\' as version), 
    xmlelement(name "renderer-v2", 
    xmlattributes(\'zone_code\' as attr, 0 as symbollevels, \'categorizedSymbol\' as type), 
    xmlelement(name symbols, 
              xmlagg(xmlelement(name symbol, 
                     xmlattributes(1 as alpha, \'fill\' as type, gid-1 as name), 
                     xmlelement(name layer, 
                     xmlattributes(0 as pass, \'SimpleFill\' as class, 0 as locked), 
                     xmlelement(name prop, 
                     xmlattributes(\'color\' as k, rgba as v)), 
                     xmlelement(name prop,
                     xmlattributes(\'outline_color\' as k, \'230,230,230,255\' as v)))))), 
                     xmlelement(name categories, 
                     xmlagg(xmlelement(name category,
                            xmlattributes(\'true\' as render, gid-1 as symbol, zone_code as value, zone_code||\' (\'|| description || \')\' as label)))))) 
from se_zones')
xml_new = ''
for row in cursor:
    print row[0]
    xml_new = row[0]

#print 'XML_New: ', xml_new # testing only

# pre-pend QGIS-specific DOCYTPE to XML
outStr= "<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>\n" + xml_new

# open destination XML file and save XML to it
outFile = open("Zones.qml", 'w')

The script is kludgy (there's no need for the for row in cursor since cursor only returns one row), but result is exactly what I wanted: a QML file that I could distribute to my colleagues so that they could style Zoned data with 3 clicks. (Bonus benefit: when theme files need to be built for different sets of categories, only the query has to change: we have ~25 different theme sets, and they were all constructed from that one script by changing the query and the destination file).

The output looks like this -

<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM' >
<qgis version="2.8.2-Wien">
  <renderer-v2 attr="zone_code" symbollevels="0" type="categorizedSymbol">
      <symbol alpha="1" type="fill" name="0">
        <layer pass="0" class="SimpleFill" locked="0">
          <prop k="color" v="240,217,250,255" />
          <prop k="outline_color" v="230,230,230,255" />
        <category render="true" symbol="0" value="B1Z" label="B1Z (Commercial 1 Zone)" />

For your specific theme you would have to write the appropriate query (which means you need to know the columns that 'drive' the style categories).

MapInfo stupidly stores styling data row-by-row (the 90s called, they want their 'style and content mixed' back), but it can be retrieved if you add the a -SQL statement to your ogr2ogr import statement adding OGR_STYLE to the retrieved set. You can then parse the 'style' column in PostgreSQL to get the styling information out.

This is the script that I use to import all TAB files in a given directory (the slashes are just to show that it's one line, broken up for clarity): the relevant additional bit is the -SQL line.

for %f in (*.tab) do 
ogr2ogr -nlt GEOMETRY \
-lco SCHEMA=test      \
-lco FID=id1          \
-f "PostgreSQL"       \
--config OGR_TRUNCATE YES \ 
-overwrite                \
-a_srs EPSG:4283          \  
-SQL "select *, CAST (OGR_STYLE AS Character (255)) AS style from %~nf" \
PG:"host=localhost user=[me] dbname=[db] password=[not telling]" \

If you then look at the imported data, you will find a column 'style' that has entries that look like


For point data it will look different, of course - it'll probably have marker types and what-not.

In all likelihood, someone with a better knowledge of how style information is stored in "the Windows 8 of GIS" (MapInfo) would be able to tell you how to get the specific colour and symbol information more directly in the -SQL statement (I've been meaning to find out, but I try to think about MapInfo as little as possible: I find it easy enough to automatically parse the 'style' column in PostgreSQL with a script).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.