Merge branch 'master' into release/5.3.2-HI

# Conflicts:
#	elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContext.java
#	elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestUpdateCallback.java
#	elasticsearch/rest/src/test/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContexFactoryIT.java
diff --git a/.travis.yml b/.travis.yml
index 9371ba8..b7100cf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,6 +5,7 @@
   - oraclejdk8
   - oraclejdk9
   - oraclejdk11
+dist: trusty
   
 before_install:
   # copy integration test config
diff --git a/CHANGES.md b/CHANGES.md
index 178507e..730def9 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,7 @@
+### Apache MetaModel _WIP_
+ * [METAMODEL-1221] - Upgrade to Elasticsearch 7.3
+ * Bind Travis build to Trusty distribution to avoid CI build failures.
+
 ### Apache MetaModel 5.3.1
 
  * [METAMODEL-1219] - Improved returning schemas for SQL Server.
diff --git a/README.md b/README.md
index 3156d74..1ffe02d 100644
--- a/README.md
+++ b/README.md
@@ -37,4 +37,4 @@
 
 ### Contributing
 
-Please see [CONTRIBUTE.md](CONTRIBUTE.md)
\ No newline at end of file
+Please see [CONTRIBUTE.md](CONTRIBUTE.md)
diff --git a/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContext.java b/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContext.java
index f943619..0528287 100644
--- a/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContext.java
+++ b/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContext.java
@@ -156,9 +156,7 @@
                         final SimpleTableDef table = detectTable(properties, tableName);
                         result.add(table);
                     } catch (Exception e) {
-                        logger
-                                .error("Unexpected error during detectTable for document mapping type '{}'", tableName,
-                                        e);
+                        logger.error("Unexpected error during detectTable for document mapping type '{}'", tableName, e);
                     }
                 }
             }
diff --git a/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestUpdateCallback.java b/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestUpdateCallback.java
index 9afb21d..3837c65 100644
--- a/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestUpdateCallback.java
+++ b/elasticsearch/rest/src/main/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestUpdateCallback.java
@@ -140,22 +140,7 @@
 
     private void executeBlocking(final ActionRequest action) {
         try {
-            final RestHighLevelClient client = getDataContext().getRestHighLevelClient();
-            final ActionResponse result;
-
-            if (action instanceof BulkRequest) {
-                result = client.bulk((BulkRequest) action, RequestOptions.DEFAULT);
-            } else if (action instanceof IndexRequest) {
-                result = client.index((IndexRequest) action, RequestOptions.DEFAULT);
-            } else if (action instanceof DeleteRequest) {
-                result = client.delete((DeleteRequest) action, RequestOptions.DEFAULT);
-            } else if (action instanceof ClearScrollRequest) {
-                result = client.clearScroll((ClearScrollRequest) action, RequestOptions.DEFAULT);
-            } else if (action instanceof SearchScrollRequest) {
-                result = client.scroll((SearchScrollRequest) action, RequestOptions.DEFAULT);
-            } else {
-                result = null;
-            }
+            final ActionResponse result = executeActionRequest(action);
 
             if (result instanceof BulkResponse && ((BulkResponse) result).hasFailures()) {
                 BulkItemResponse[] failedItems = ((BulkResponse) result).getItems();
@@ -175,6 +160,22 @@
         }
     }
 
+    private ActionResponse executeActionRequest(final ActionRequest action) throws IOException {
+        final RestHighLevelClient client = getDataContext().getRestHighLevelClient();
+        if (action instanceof BulkRequest) {
+            return client.bulk((BulkRequest) action, RequestOptions.DEFAULT);
+        } else if (action instanceof IndexRequest) {
+            return client.index((IndexRequest) action, RequestOptions.DEFAULT);
+        } else if (action instanceof DeleteRequest) {
+            return client.delete((DeleteRequest) action, RequestOptions.DEFAULT);
+        } else if (action instanceof ClearScrollRequest) {
+            return client.clearScroll((ClearScrollRequest) action, RequestOptions.DEFAULT);
+        } else if (action instanceof SearchScrollRequest) {
+            return client.scroll((SearchScrollRequest) action, RequestOptions.DEFAULT);
+        }
+        return null;
+    }
+
     private BulkRequest getBulkRequest() {
         if (bulkRequest == null) {
             bulkRequest = new BulkRequest();
diff --git a/elasticsearch/rest/src/test/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContexFactoryIT.java b/elasticsearch/rest/src/test/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContexFactoryIT.java
index ad97bed..d18d296 100644
--- a/elasticsearch/rest/src/test/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContexFactoryIT.java
+++ b/elasticsearch/rest/src/test/java/org/apache/metamodel/elasticsearch/rest/ElasticSearchRestDataContexFactoryIT.java
@@ -69,12 +69,10 @@
                 .builder(new HttpHost(dockerHostAddress, ElasticSearchRestDataContextIT.DEFAULT_REST_CLIENT_PORT)));
         externalClient.indices().create(new CreateIndexRequest(INDEX_NAME), RequestOptions.DEFAULT);
 
-        final PutMappingRequest putMappingRequest = new PutMappingRequest(INDEX_NAME);
-        putMappingRequest
-                .source(ElasticSearchUtils
-                        .getMappingSource(new MutableTable(DEFAULT_TABLE_NAME, TableType.TABLE, new MutableSchema(
-                                INDEX_NAME), new MutableColumn("name", ColumnType.STRING), new MutableColumn("age",
-                                        ColumnType.INTEGER))));
+        final MutableTable table = new MutableTable(DEFAULT_TABLE_NAME, TableType.TABLE, new MutableSchema(INDEX_NAME),
+                new MutableColumn("name", ColumnType.STRING), new MutableColumn("age", ColumnType.INTEGER));
+        final PutMappingRequest putMappingRequest = new PutMappingRequest(INDEX_NAME)
+                .source(ElasticSearchUtils.getMappingSource(table));
 
         externalClient.indices().putMapping(putMappingRequest, RequestOptions.DEFAULT);
 
diff --git a/excel/pom.xml b/excel/pom.xml
index 7f8e8f0..e9f839b 100644
--- a/excel/pom.xml
+++ b/excel/pom.xml
@@ -40,7 +40,7 @@
 		<dependency>
 			<groupId>org.apache.poi</groupId>
 			<artifactId>poi-ooxml</artifactId>
-			<version>4.0.1</version>
+			<version>4.1.1</version>
 			<exclusions>
 				<exclusion>
 					<groupId>commons-logging</groupId>
diff --git a/excel/src/main/java/org/apache/metamodel/excel/DefaultSpreadsheetReaderDelegate.java b/excel/src/main/java/org/apache/metamodel/excel/DefaultSpreadsheetReaderDelegate.java
index 97ba50f..98cdefe 100644
--- a/excel/src/main/java/org/apache/metamodel/excel/DefaultSpreadsheetReaderDelegate.java
+++ b/excel/src/main/java/org/apache/metamodel/excel/DefaultSpreadsheetReaderDelegate.java
@@ -18,6 +18,7 @@
  */
 package org.apache.metamodel.excel;
 
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -41,6 +42,8 @@
 import org.apache.metamodel.util.FileHelper;
 import org.apache.metamodel.util.Resource;
 import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.usermodel.Workbook;
@@ -53,6 +56,9 @@
  */
 final class DefaultSpreadsheetReaderDelegate implements SpreadsheetReaderDelegate {
 
+    static final ColumnType DEFAULT_COLUMN_TYPE = ColumnType.STRING;
+    static final ColumnType LEGACY_COLUMN_TYPE = ColumnType.VARCHAR;
+
     private static final Logger logger = LoggerFactory.getLogger(DefaultSpreadsheetReaderDelegate.class);
 
     private final Resource _resource;
@@ -128,6 +134,11 @@
             row = rowIterator.next();
         }
 
+        final ColumnType[] columnTypes = getColumnTypes(sheet);
+        if (columnTypes == null) {
+            return table;
+        }
+
         final int columnNameLineNumber = _configuration.getColumnNameLineNumber();
         if (columnNameLineNumber == ExcelConfiguration.NO_COLUMN_NAME_LINE) {
 
@@ -146,30 +157,19 @@
                     columnNamingSession.getNextColumnName(new ColumnNamingContextImpl(i));
                 }
 
-                for (int j = offset; j < row.getLastCellNum(); j++) {
-                    final ColumnNamingContext namingContext = new ColumnNamingContextImpl(table, null, j);
+                for (int i = offset; i < row.getLastCellNum(); i++) {
+                    final ColumnNamingContext namingContext = new ColumnNamingContextImpl(table, null, i);
                     final Column column = new MutableColumn(columnNamingSession.getNextColumnName(namingContext),
-                            ColumnType.STRING, table, j, true);
+                            columnTypes[i], table, i, true);
                     table.addColumn(column);
                 }
             }
 
         } else {
+            row = iterateToColumnNameRow(rowIterator, row);
 
-            boolean hasColumns = true;
-
-            // iterate to the column name line number (if above 1)
-            for (int j = 1; j < columnNameLineNumber; j++) {
-                if (rowIterator.hasNext()) {
-                    row = rowIterator.next();
-                } else {
-                    hasColumns = false;
-                    break;
-                }
-            }
-
-            if (hasColumns) {
-                createColumns(table, wb, row);
+            if (row != null) {
+                createColumns(table, wb, row, columnTypes);
             }
         }
 
@@ -177,13 +177,85 @@
     }
 
     /**
+     * Iterate to the column name row if the configured ColumnNameLineNumber is above 1.
+     * @param rowIterator
+     * @param currentRow
+     * @return Returns the column name row. Returns the current row if the configured ColumnNameLineNumber is 1.
+     * Returns null if the columnName row is not found.
+     */
+    private Row iterateToColumnNameRow(final Iterator<Row> rowIterator, final Row currentRow) {
+        Row row = currentRow;
+
+        // iterate to the column name line number (if above 1)
+        for (int i = 1; i < _configuration.getColumnNameLineNumber(); i++) {
+            if (rowIterator.hasNext()) {
+                row = rowIterator.next();
+            } else {
+                return null;
+            }
+        }
+
+        return row;
+    }
+
+    /**
+     * Get an array of {@link ColumnType}s. The length of the array is determined by the header row. If there's no
+     * configured column name line, then the first data row is used. If the {@link ColumnType} should be detected, then
+     * this is done by using the data rows only. If this shouldn't be detected, then the array is filled with either
+     * default column type when there is no column name line or legacy column type when there is a column name line.
+     * @param sheet
+     * @return
+     */
+    private ColumnType[] getColumnTypes(final Sheet sheet) {
+        // To find the array length we need the header
+        final Iterator<Row> iterator = ExcelUtils.getRowIterator(sheet, _configuration, false);
+        Row row;
+        if (_configuration.getColumnNameLineNumber() == ExcelConfiguration.NO_COLUMN_NAME_LINE) {
+            row = findTheFirstNonEmptyRow(iterator);
+        } else {
+            row = iterateToColumnNameRow(iterator, iterator.next());
+        }
+        if (row == null) {
+            return null;
+        }
+
+        final ColumnType[] columnTypes = new ColumnType[row.getLastCellNum()];
+
+        if (_configuration.isDetectColumnTypes()) {
+            // Now we need the first data row
+            row = findTheFirstNonEmptyRow(iterator);
+            if (row != null) {
+                new ColumnTypeScanner(sheet).detectColumnTypes(row, iterator, columnTypes);
+            }
+        } else {
+            if (_configuration.getColumnNameLineNumber() == ExcelConfiguration.NO_COLUMN_NAME_LINE) {
+                Arrays.fill(columnTypes, DEFAULT_COLUMN_TYPE);
+            } else {
+                Arrays.fill(columnTypes, LEGACY_COLUMN_TYPE);
+            }
+        }
+        return columnTypes;
+    }
+
+    private static Row findTheFirstNonEmptyRow(final Iterator<Row> rowIterator) {
+        while (rowIterator.hasNext()) {
+            final Row row = rowIterator.next();
+            if (row != null) {
+                return row;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Builds columns based on row/cell values.
      * 
      * @param table
      * @param wb
      * @param row
      */
-    private void createColumns(MutableTable table, Workbook wb, Row row) {
+    private void createColumns(final MutableTable table, final Workbook wb, final Row row,
+            final ColumnType[] columnTypes) {
         if (row == null) {
             logger.warn("Cannot create columns based on null row!");
             return;
@@ -193,15 +265,16 @@
         final int offset = getColumnOffset(row);
 
         // build columns based on cell values.
-        try (final ColumnNamingSession columnNamingSession = _configuration.getColumnNamingStrategy()
+        try (final ColumnNamingSession columnNamingSession = _configuration
+                .getColumnNamingStrategy()
                 .startColumnNamingSession()) {
-            for (int j = offset; j < rowLength; j++) {
-                final Cell cell = row.getCell(j);
+            for (int i = offset; i < rowLength; i++) {
+                final Cell cell = row.getCell(i);
                 final String intrinsicColumnName = ExcelUtils.getCellValue(wb, cell);
                 final ColumnNamingContext columnNamingContext = new ColumnNamingContextImpl(table, intrinsicColumnName,
-                        j);
+                        i);
                 final String columnName = columnNamingSession.getNextColumnName(columnNamingContext);
-                final Column column = new MutableColumn(columnName, ColumnType.VARCHAR, table, j, true);
+                final Column column = new MutableColumn(columnName, columnTypes[i], table, i, true);
                 table.addColumn(column);
             }
         }
@@ -224,4 +297,111 @@
         }
         return offset;
     }
+    
+    private class ColumnTypeScanner {
+        final FormulaEvaluator formulaEvaluator;
+
+        ColumnTypeScanner(final Sheet sheet) {
+            formulaEvaluator = sheet.getWorkbook().getCreationHelper().createFormulaEvaluator();
+        }
+
+        private void detectColumnTypes(final Row firstRow, final Iterator<Row> dataRowIterator,
+                final ColumnType[] columnTypes) {
+            detectColumnTypesFirstRow(firstRow, columnTypes);
+            detectColumnTypesOtherRows(dataRowIterator, columnTypes);
+
+            // If all cells are null, then this loop sets the column type to the default
+            for (int i = 0; i < columnTypes.length; i++) {
+                if (columnTypes[i] == null) {
+                    columnTypes[i] = DEFAULT_COLUMN_TYPE;
+                }
+            }
+        }
+
+        private void detectColumnTypesFirstRow(final Row firstRow, final ColumnType[] columnTypes) {
+            if (firstRow != null && firstRow.getLastCellNum() > 0) {
+                for (int i = getColumnOffset(firstRow); i < columnTypes.length; i++) {
+                    if (firstRow.getCell(i) != null) {
+                        columnTypes[i] = determineColumnTypeFromCell(firstRow.getCell(i));
+                    }
+                }
+            }
+        }
+
+        private void detectColumnTypesOtherRows(final Iterator<Row> dataRowIterator, final ColumnType[] columnTypes) {
+            int numberOfLinesToScan = _configuration.getNumberOfLinesToScan() - 1;
+
+            while (dataRowIterator.hasNext() && numberOfLinesToScan-- > 0) {
+                final Row currentRow = dataRowIterator.next();
+                if (currentRow != null && currentRow.getLastCellNum() > 0) {
+                    for (int i = getColumnOffset(currentRow); i < columnTypes.length; i++) {
+                        final ColumnType detectNewColumnType = detectNewColumnTypeCell(columnTypes[i], currentRow
+                                .getCell(i));
+                        if (detectNewColumnType != null) {
+                            columnTypes[i] = detectNewColumnType;
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Tries to detect a new {@link ColumnType} for a cell.
+         * @param currentColumnType
+         * @param cell
+         * @return Returns a new {@link ColumnType} when detected. Otherwise null is returned.
+         */
+        private ColumnType detectNewColumnTypeCell(final ColumnType currentColumnType, final Cell cell) {
+            // Can't detect something new if it's already on the default.
+            if (currentColumnType != null && currentColumnType.equals(DEFAULT_COLUMN_TYPE)) {
+                return null;
+            }
+            // Skip if the cell is null. This way 1 missing cell can't influence the column type of all other cells.
+            if (cell == null) {
+                return null;
+            }
+
+            final ColumnType detectedColumnType = determineColumnTypeFromCell(cell);
+            if (currentColumnType == null) {
+                return detectedColumnType;
+            } else if (!currentColumnType.equals(detectedColumnType)) {
+                // If the column type is Double and a Integer is detected, then don't set it to Integer
+                if (currentColumnType.equals(ColumnType.INTEGER) && detectedColumnType.equals(ColumnType.DOUBLE)) {
+                    // If the column type is Integer and a Double is detected, then set it to Double
+                    return detectedColumnType;
+                } else if (currentColumnType.equals(ColumnType.DOUBLE) && detectedColumnType
+                        .equals(ColumnType.INTEGER)) {
+                    return null;
+                } else {
+                    return DEFAULT_COLUMN_TYPE;
+                }
+            }
+            return null;
+        }
+
+        private ColumnType determineColumnTypeFromCell(final Cell cell) {
+            switch (cell.getCellType()) {
+            case NUMERIC:
+                if (DateUtil.isCellDateFormatted(cell)) {
+                    return ColumnType.DATE;
+                } else {
+                    return cell.getNumericCellValue() % 1 == 0 ? ColumnType.INTEGER : ColumnType.DOUBLE;
+                }
+            case BOOLEAN:
+                return ColumnType.BOOLEAN;
+            case FORMULA:
+                return determineColumnTypeFromCell(formulaEvaluator.evaluateInCell(cell));
+            case STRING:
+                // fall through
+            case BLANK:
+                // fall through
+            case _NONE:
+                // fall through
+            case ERROR:
+                // fall through
+            default:
+                return DEFAULT_COLUMN_TYPE;
+            }
+        }
+    }
 }
diff --git a/excel/src/main/java/org/apache/metamodel/excel/ExcelConfiguration.java b/excel/src/main/java/org/apache/metamodel/excel/ExcelConfiguration.java
index 4779bb1..a768f6d 100644
--- a/excel/src/main/java/org/apache/metamodel/excel/ExcelConfiguration.java
+++ b/excel/src/main/java/org/apache/metamodel/excel/ExcelConfiguration.java
@@ -37,26 +37,39 @@
 
 	public static final int NO_COLUMN_NAME_LINE = 0;
 	public static final int DEFAULT_COLUMN_NAME_LINE = 1;
+    public static final int DEFAULT_NUMBERS_OF_LINES_TO_SCAN = 10;
 
 	private final int columnNameLineNumber;
 	private final ColumnNamingStrategy columnNamingStrategy;
 	private final boolean skipEmptyLines;
 	private final boolean skipEmptyColumns;
+    private final boolean detectColumnTypes;
+    private final int numberOfLinesToScan;
 
 	public ExcelConfiguration() {
 		this(DEFAULT_COLUMN_NAME_LINE, true, false);
 	}
 
-    public ExcelConfiguration(int columnNameLineNumber, boolean skipEmptyLines, boolean skipEmptyColumns) {
+    public ExcelConfiguration(final int columnNameLineNumber, final boolean skipEmptyLines,
+            final boolean skipEmptyColumns) {
         this(columnNameLineNumber, null, skipEmptyLines, skipEmptyColumns);
     }
 
-    public ExcelConfiguration(int columnNameLineNumber, ColumnNamingStrategy columnNamingStrategy,
-            boolean skipEmptyLines, boolean skipEmptyColumns) {
+    public ExcelConfiguration(final int columnNameLineNumber, final ColumnNamingStrategy columnNamingStrategy,
+            final boolean skipEmptyLines, final boolean skipEmptyColumns) {
+        this(columnNameLineNumber, columnNamingStrategy, skipEmptyLines, skipEmptyColumns, false,
+                DEFAULT_NUMBERS_OF_LINES_TO_SCAN);
+    }
+
+    public ExcelConfiguration(final int columnNameLineNumber, final ColumnNamingStrategy columnNamingStrategy,
+            final boolean skipEmptyLines, final boolean skipEmptyColumns, final boolean detectColumnTypes,
+            final int numberOfLinesToScan) {
         this.columnNameLineNumber = columnNameLineNumber;
         this.skipEmptyLines = skipEmptyLines;
         this.skipEmptyColumns = skipEmptyColumns;
         this.columnNamingStrategy = columnNamingStrategy;
+        this.detectColumnTypes = detectColumnTypes;
+        this.numberOfLinesToScan = numberOfLinesToScan;
     }
     
     /**
@@ -102,17 +115,42 @@
 		return skipEmptyColumns;
 	}
 
+    /**
+     * Defines if columns in the excel spreadsheet should be detected on data types while reading the spreadsheet.
+     * If this detection configuration is set to false and there's no column name line configured, then all column
+     * types will be String.
+     * If this detection configuration is set to false and there's a column name line configured, then all column
+     * types will be VarChar.
+     * 
+     * @return a boolean indicating whether or not to validate column types.
+     */
+    public boolean isDetectColumnTypes() {
+        return detectColumnTypes;
+    }
+
+    /**
+     * The number of lines to scan when detecting the column types
+     * 
+     * @return an int indicating the numbers of lines that will be scanned
+     */
+    public int getNumberOfLinesToScan() {
+        return numberOfLinesToScan;
+    }
+
 	@Override
 	protected void decorateIdentity(List<Object> identifiers) {
 		identifiers.add(columnNameLineNumber);
 		identifiers.add(skipEmptyLines);
 		identifiers.add(skipEmptyColumns);
+        identifiers.add(detectColumnTypes);
+        identifiers.add(numberOfLinesToScan);
 	}
 
-	@Override
-	public String toString() {
-		return "ExcelConfiguration[columnNameLineNumber="
-				+ columnNameLineNumber + ", skipEmptyLines=" + skipEmptyLines
-				+ ", skipEmptyColumns=" + skipEmptyColumns + "]";
-	}
+    @Override
+    public String toString() {
+        return String
+                .format("ExcelConfiguration[columnNameLineNumber=%s, skipEmptyLines=%s, skipEmptyColumns=%s, "
+                        + "detectColumnTypes=%s, numbersOfLinesToScan=%s]", columnNameLineNumber, skipEmptyLines,
+                        skipEmptyColumns, detectColumnTypes, numberOfLinesToScan);
+    }
 }
diff --git a/excel/src/main/java/org/apache/metamodel/excel/ExcelDataContext.java b/excel/src/main/java/org/apache/metamodel/excel/ExcelDataContext.java
index b1f8149..0829109 100644
--- a/excel/src/main/java/org/apache/metamodel/excel/ExcelDataContext.java
+++ b/excel/src/main/java/org/apache/metamodel/excel/ExcelDataContext.java
@@ -189,7 +189,7 @@
                 if (_spreadsheetReaderDelegate == null) {
                     _spreadsheetReaderDelegate = _resource.read(in -> {
                         try {
-                            if (FileMagic.valueOf(in) == FileMagic.OOXML) {
+                            if (FileMagic.valueOf(in) == FileMagic.OOXML && !_configuration.isDetectColumnTypes()) {
                                 return new XlsxSpreadsheetReaderDelegate(_resource, _configuration);
                             } else {
                                 return new DefaultSpreadsheetReaderDelegate(_resource, _configuration);
diff --git a/excel/src/main/java/org/apache/metamodel/excel/ExcelUtils.java b/excel/src/main/java/org/apache/metamodel/excel/ExcelUtils.java
index 2da6ef3..21491ec 100644
--- a/excel/src/main/java/org/apache/metamodel/excel/ExcelUtils.java
+++ b/excel/src/main/java/org/apache/metamodel/excel/ExcelUtils.java
@@ -19,7 +19,6 @@
 package org.apache.metamodel.excel;
 
 import java.io.File;
-import java.text.NumberFormat;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
@@ -37,21 +36,22 @@
 import org.apache.metamodel.data.Style.SizeUnit;
 import org.apache.metamodel.data.StyleBuilder;
 import org.apache.metamodel.query.SelectItem;
+import org.apache.metamodel.schema.ColumnType;
 import org.apache.metamodel.schema.Table;
 import org.apache.metamodel.util.DateUtils;
 import org.apache.metamodel.util.FileHelper;
 import org.apache.metamodel.util.FileResource;
-import org.apache.metamodel.util.FormatHelper;
 import org.apache.metamodel.util.InMemoryResource;
 import org.apache.metamodel.util.Resource;
-import org.apache.poi.hssf.usermodel.HSSFDateUtil;
 import org.apache.poi.hssf.usermodel.HSSFFont;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.hssf.util.HSSFColor;
-import org.apache.poi.ss.formula.FormulaParseException;
+import org.apache.poi.ss.usermodel.BuiltinFormats;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.CellStyle;
 import org.apache.poi.ss.usermodel.Color;
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.ss.usermodel.DateUtil;
 import org.apache.poi.ss.usermodel.FillPatternType;
 import org.apache.poi.ss.usermodel.Font;
 import org.apache.poi.ss.usermodel.FontUnderline;
@@ -76,8 +76,6 @@
 
     private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class);
 
-    private static final NumberFormat _numberFormat = FormatHelper.getUiNumberFormat();
-
     private ExcelUtils() {
         // prevent instantiation
     }
@@ -176,8 +174,6 @@
             return null;
         }
 
-        final String cellCoordinate = "(" + cell.getRowIndex() + "," + cell.getColumnIndex() + ")";
-
         final String result;
 
         switch (cell.getCellType()) {
@@ -189,30 +185,13 @@
             result = Boolean.toString(cell.getBooleanCellValue());
             break;
         case ERROR:
-            String errorResult;
-            try {
-                byte errorCode = cell.getErrorCellValue();
-                FormulaError formulaError = FormulaError.forInt(errorCode);
-                errorResult = formulaError.getString();
-            } catch (RuntimeException e) {
-                logger.debug("Getting error code for {} failed!: {}", cellCoordinate, e.getMessage());
-                if (cell instanceof XSSFCell) {
-                    // hack to get error string, which is available
-                    String value = ((XSSFCell) cell).getErrorCellString();
-                    errorResult = value;
-                } else {
-                    logger.error("Couldn't handle unexpected error scenario in cell: " + cellCoordinate, e);
-                    throw e;
-                }
-            }
-            result = errorResult;
+            result = getErrorResult(cell);
             break;
         case FORMULA:
-            // result = cell.getCellFormula();
             result = getFormulaCellValue(wb, cell);
             break;
         case NUMERIC:
-            if (HSSFDateUtil.isCellDateFormatted(cell)) {
+            if (DateUtil.isCellDateFormatted(cell)) {
                 Date date = cell.getDateCellValue();
                 if (date == null) {
                     result = null;
@@ -220,9 +199,7 @@
                     result = DateUtils.createDateFormat().format(date);
                 }
             } else {
-                // TODO: Consider not formatting it, but simple using
-                // Double.toString(...)
-                result = _numberFormat.format(cell.getNumericCellValue());
+                result = getNumericCellValueAsString(cell.getCellStyle(), cell.getNumericCellValue());
             }
             break;
         case STRING:
@@ -232,18 +209,93 @@
             throw new IllegalStateException("Unknown cell type: " + cell.getCellType());
         }
 
-        logger.debug("cell {} resolved to value: {}", cellCoordinate, result);
+        logger.debug("cell ({},{}) resolved to value: {}", cell.getRowIndex(), cell.getColumnIndex(), result);
 
         return result;
     }
 
-    private static String getFormulaCellValue(Workbook wb, Cell cell) {
+    private static Object getCellValueAsObject(final Workbook workbook, final Cell cell) {
+        if (cell == null) {
+            return null;
+        }
+
+        final Object result;
+
+        switch (cell.getCellType()) {
+        case BLANK:
+        case _NONE:
+            result = null;
+            break;
+        case BOOLEAN:
+            result = Boolean.valueOf(cell.getBooleanCellValue());
+            break;
+        case ERROR:
+            result = getErrorResult(cell);
+            break;
+        case FORMULA:
+            result = getFormulaCellValueAsObject(workbook, cell);
+            break;
+        case NUMERIC:
+            if (DateUtil.isCellDateFormatted(cell)) {
+                result = cell.getDateCellValue();
+            } else {
+                result = getDoubleAsNumber(cell.getNumericCellValue());
+            }
+            break;
+        case STRING:
+            result = cell.getRichStringCellValue().getString();
+            break;
+        default:
+            throw new IllegalStateException("Unknown cell type: " + cell.getCellType());
+        }
+
+        logger.debug("cell ({},{}) resolved to value: {}", cell.getRowIndex(), cell.getColumnIndex(), result);
+
+        return result;
+    }
+
+    private static String getErrorResult(final Cell cell) {
+        try {
+            return FormulaError.forInt(cell.getErrorCellValue()).getString();
+        } catch (final RuntimeException e) {
+            logger
+                    .debug("Getting error code for ({},{}) failed!: {}", cell.getRowIndex(), cell.getColumnIndex(), e
+                            .getMessage());
+            if (cell instanceof XSSFCell) {
+                // hack to get error string, which is available
+                return ((XSSFCell) cell).getErrorCellString();
+            } else {
+                logger
+                        .error("Couldn't handle unexpected error scenario in cell: ({},{})", cell.getRowIndex(), cell
+                                .getColumnIndex());
+                throw e;
+            }
+        }
+    }
+
+    private static Object evaluateCell(final Workbook workbook, final Cell cell, final ColumnType expectedColumnType) {
+        final Object value = getCellValueAsObject(workbook, cell);
+        if (value == null || value.getClass().equals(expectedColumnType.getJavaEquivalentClass())) {
+            return value;
+        }
+
+        // Don't log when an Integer value is in a Double column type
+        if (!(value.getClass().equals(Integer.class) && expectedColumnType
+                .getJavaEquivalentClass()
+                .equals(Double.class)) && logger.isWarnEnabled()) {
+            logger
+                    .warn("Cell ({},{}) has the value '{}' of data type '{}', which doesn't match the detected "
+                            + "column's data type '{}'. This cell gets value NULL in the DataSet.", cell.getRowIndex(),
+                            cell.getColumnIndex(), value, value.getClass().getSimpleName(), expectedColumnType);
+        }
+        return null;
+    }
+
+    private static String getFormulaCellValue(Workbook workbook, Cell cell) {
         // first try with a cached/precalculated value
         try {
             double numericCellValue = cell.getNumericCellValue();
-            // TODO: Consider not formatting it, but simple using
-            // Double.toString(...)
-            return _numberFormat.format(numericCellValue);
+            return getNumericCellValueAsString(cell.getCellStyle(), numericCellValue);
         } catch (Exception e) {
             if (logger.isInfoEnabled()) {
                 logger.info("Failed to fetch cached/precalculated formula value of cell: " + cell, e);
@@ -251,34 +303,62 @@
         }
 
         // evaluate cell first, if possible
+        final Cell evaluatedCell = getEvaluatedCell(workbook, cell);
+        if (evaluatedCell != null) {
+            return getCellValue(workbook, evaluatedCell);
+        } else {
+            // last resort: return the string formula
+            return cell.getCellFormula();
+        }
+    }
+
+    private static Object getFormulaCellValueAsObject(final Workbook workbook, final Cell cell) {
+        // first try with a cached/precalculated value
         try {
+            return getDoubleAsNumber(cell.getNumericCellValue());
+        } catch (final Exception e) {
             if (logger.isInfoEnabled()) {
-                logger.info("cell({},{}) is a formula. Attempting to evaluate: {}",
-                        new Object[] { cell.getRowIndex(), cell.getColumnIndex(), cell.getCellFormula() });
-            }
-
-            final FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
-
-            // calculates the formula and puts it's value back into the cell
-            final Cell evaluatedCell = evaluator.evaluateInCell(cell);
-
-            return getCellValue(wb, evaluatedCell);
-        } catch (RuntimeException e) {
-            logger.warn("Exception occurred while evaluating formula at position ({},{}): {}",
-                    new Object[] { cell.getRowIndex(), cell.getColumnIndex(), e.getMessage() });
-            // Some exceptions we simply log - result will be then be the
-            // actual formula
-            if (e instanceof FormulaParseException) {
-                logger.error("Parse exception occurred while evaluating cell formula: " + cell, e);
-            } else if (e instanceof IllegalArgumentException) {
-                logger.error("Illegal formula argument occurred while evaluating cell formula: " + cell, e);
-            } else {
-                logger.error("Unexpected exception occurred while evaluating cell formula: " + cell, e);
+                logger.info("Failed to fetch cached/precalculated formula value of cell: " + cell, e);
             }
         }
 
-        // last resort: return the string formula
-        return cell.getCellFormula();
+        // evaluate cell first, if possible
+        final Cell evaluatedCell = getEvaluatedCell(workbook, cell);
+        if (evaluatedCell != null) {
+            return getCellValueAsObject(workbook, evaluatedCell);
+        } else {
+            // last resort: return the string formula
+            return cell.getCellFormula();
+        }
+    }
+
+    private static Cell getEvaluatedCell(final Workbook workbook, final Cell cell) {
+        try {
+            if (logger.isInfoEnabled()) {
+                logger
+                        .info("cell ({},{}) is a formula. Attempting to evaluate: {}", cell.getRowIndex(), cell
+                                .getColumnIndex(), cell.getCellFormula());
+            }
+
+            final FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
+
+            // calculates the formula and puts it's value back into the cell
+            return evaluator.evaluateInCell(cell);
+        } catch (RuntimeException e) {
+            logger
+                    .warn("Exception occurred while evaluating formula at position ({},{}): {}", cell.getRowIndex(),
+                            cell.getColumnIndex(), e.getMessage());
+        }
+        return null;
+    }
+
+    private static Number getDoubleAsNumber(final double value) {
+        final Double doubleValue = Double.valueOf(value);
+        if (doubleValue % 1 == 0 && doubleValue <= Integer.MAX_VALUE) {
+            return Integer.valueOf(doubleValue.intValue());
+        } else {
+            return doubleValue;
+        }
     }
 
     public static Style getCellStyle(Workbook workbook, Cell cell) {
@@ -412,15 +492,23 @@
      * @param selectItems select items of the columns in the table
      * @return
      */
-    public static DefaultRow createRow(Workbook workbook, Row row, DataSetHeader header) {
+    public static DefaultRow createRow(final Workbook workbook, final Row row, final DataSetHeader header) {
         final int size = header.size();
-        final String[] values = new String[size];
+        final Object[] values = new Object[size];
         final Style[] styles = new Style[size];
         if (row != null) {
             for (int i = 0; i < size; i++) {
                 final int columnNumber = header.getSelectItem(i).getColumn().getColumnNumber();
+                final ColumnType columnType = header.getSelectItem(i).getColumn().getType();
                 final Cell cell = row.getCell(columnNumber);
-                final String value = ExcelUtils.getCellValue(workbook, cell);
+                final Object value;
+                if (columnType.equals(DefaultSpreadsheetReaderDelegate.DEFAULT_COLUMN_TYPE) || columnType
+                        .equals(DefaultSpreadsheetReaderDelegate.LEGACY_COLUMN_TYPE)) {
+                    value = ExcelUtils.getCellValue(workbook, cell);
+                } else {
+                    value = ExcelUtils.evaluateCell(workbook, cell, columnType);
+                }
+
                 final Style style = ExcelUtils.getCellStyle(workbook, cell);
                 values[i] = value;
                 styles[i] = style;
@@ -443,4 +531,14 @@
         final DataSet dataSet = new XlsDataSet(selectItems, workbook, rowIterator);
         return dataSet;
     }
+
+    private static String getNumericCellValueAsString(final CellStyle cellStyle, final double cellValue) {
+        final int formatIndex = cellStyle.getDataFormat();
+        String formatString = cellStyle.getDataFormatString();
+        if (formatString == null) {
+            formatString = BuiltinFormats.getBuiltinFormat(formatIndex);
+        }
+        final DataFormatter formatter = new DataFormatter();
+        return formatter.formatRawCellContents(cellValue, formatIndex, formatString);
+    }
 }
diff --git a/excel/src/test/java/org/apache/metamodel/excel/ExcelConfigurationTest.java b/excel/src/test/java/org/apache/metamodel/excel/ExcelConfigurationTest.java
index 6e7559c..f54980f 100644
--- a/excel/src/test/java/org/apache/metamodel/excel/ExcelConfigurationTest.java
+++ b/excel/src/test/java/org/apache/metamodel/excel/ExcelConfigurationTest.java
@@ -18,18 +18,17 @@
  */
 package org.apache.metamodel.excel;
 
-import org.apache.metamodel.excel.ExcelConfiguration;
-
 import junit.framework.TestCase;
 
 public class ExcelConfigurationTest extends TestCase {
 
-	public void testToString() throws Exception {
-		ExcelConfiguration conf = new ExcelConfiguration(1, true, false);
-		assertEquals(
-				"ExcelConfiguration[columnNameLineNumber=1, skipEmptyLines=true, skipEmptyColumns=false]",
-				conf.toString());
-	}
+    public void testToString() throws Exception {
+        final ExcelConfiguration conf = new ExcelConfiguration(1, true, false);
+        assertEquals(String
+                .format("ExcelConfiguration[columnNameLineNumber=%s, skipEmptyLines=%s, skipEmptyColumns=%s, "
+                        + "detectColumnTypes=%s, numbersOfLinesToScan=%s]", ExcelConfiguration.DEFAULT_COLUMN_NAME_LINE,
+                        true, false, false, ExcelConfiguration.DEFAULT_NUMBERS_OF_LINES_TO_SCAN), conf.toString());
+    }
 
 	public void testEquals() throws Exception {
 		ExcelConfiguration conf1 = new ExcelConfiguration(1, true, false);
diff --git a/excel/src/test/java/org/apache/metamodel/excel/ExcelDataContextTest.java b/excel/src/test/java/org/apache/metamodel/excel/ExcelDataContextTest.java
index 13cfdec..7fdfff9 100644
--- a/excel/src/test/java/org/apache/metamodel/excel/ExcelDataContextTest.java
+++ b/excel/src/test/java/org/apache/metamodel/excel/ExcelDataContextTest.java
@@ -21,8 +21,10 @@
 import java.io.File;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.IntStream;
 
 import org.apache.metamodel.DataContext;
+import org.apache.metamodel.MetaModelException;
 import org.apache.metamodel.MetaModelHelper;
 import org.apache.metamodel.UpdateCallback;
 import org.apache.metamodel.UpdateScript;
@@ -30,15 +32,19 @@
 import org.apache.metamodel.data.Row;
 import org.apache.metamodel.data.Style;
 import org.apache.metamodel.data.StyleBuilder;
+import org.apache.metamodel.insert.InsertInto;
 import org.apache.metamodel.query.Query;
 import org.apache.metamodel.schema.Column;
+import org.apache.metamodel.schema.ColumnType;
 import org.apache.metamodel.schema.Schema;
 import org.apache.metamodel.schema.Table;
 import org.apache.metamodel.schema.naming.CustomColumnNamingStrategy;
+import org.apache.metamodel.update.Update;
 import org.apache.metamodel.util.DateUtils;
 import org.apache.metamodel.util.FileHelper;
 import org.apache.metamodel.util.FileResource;
 import org.apache.metamodel.util.Month;
+import org.junit.Test;
 
 import junit.framework.TestCase;
 
@@ -792,4 +798,154 @@
         assertNotNull(table.getColumnByName(secondColumnName));
         assertNotNull(table.getColumnByName(thirdColumnName));
     }
+
+    public void testDetectingDifferentDataTypesInXls() throws Exception {
+        detectingDataTypes("src/test/resources/different_datatypes.xls");
+    }
+
+    public void testDifferentDataTypesInXlsx() throws Exception {
+        detectingDataTypes("src/test/resources/different_datatypes.xlsx");
+    }
+
+    private void detectingDataTypes(final String file) {
+        final DataContext dataContext = new ExcelDataContext(copyOf(file), new ExcelConfiguration(
+                ExcelConfiguration.DEFAULT_COLUMN_NAME_LINE, null, true, false, true, 19));
+
+        final Schema schema = dataContext.getDefaultSchema();
+        assertEquals(2, schema.getTableCount());
+
+        final Table table = schema.getTables().get(0);
+        assertEquals("INTEGER", table.getColumns().get(0).getName());
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(0).getType());
+        assertEquals("TEXT", table.getColumns().get(1).getName());
+        assertEquals(ColumnType.STRING, table.getColumns().get(1).getType());
+        assertEquals("FORMULA", table.getColumns().get(2).getName());
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(2).getType());
+        assertEquals("MIXING_DOUBLE_AND_INT", table.getColumns().get(3).getName());
+        assertEquals(ColumnType.DOUBLE, table.getColumns().get(3).getType());
+        assertEquals("MIXING_OTHER_DATATYPES", table.getColumns().get(4).getName());
+        assertEquals(ColumnType.STRING, table.getColumns().get(4).getType());
+        final DataSet countDataSet = dataContext.query().from(table).selectCount().execute();
+        assertTrue(countDataSet.next());
+        assertEquals(20L, countDataSet.getRow().getValue(0));
+        assertFalse(countDataSet.next());
+    }
+
+    public void testCellValueWithWrongDatatypeIsSetToNull() {
+        // Unless Integers and Doubles are mixed all other incorrect values will be converted to null with a warning
+        final DataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/different_datatypes.xls"),
+                new ExcelConfiguration(ExcelConfiguration.DEFAULT_COLUMN_NAME_LINE, null, true, false, true, 19));
+        final Table table = dataContext.getDefaultSchema().getTables().get(0);
+        final DataSet testWrongDatatypeDataSet = dataContext
+                .query()
+                .from(table)
+                .select("MIXING_DOUBLE_AND_INT")
+                .execute();
+        IntStream.range(0, 20).forEach(i -> assertTrue(testWrongDatatypeDataSet.next()));
+        assertNull(testWrongDatatypeDataSet.getRow().getValue(0));
+        assertFalse(testWrongDatatypeDataSet.next());
+    }
+
+    public void testDetectingDataTypeNotSkippingLinesAndColumnsUsingNameLine() {
+        final ExcelDataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/skipped_lines.xlsx"),
+                new ExcelConfiguration(6, null, false, false, true, 3));
+        final Table table = dataContext.getDefaultSchema().getTables().get(0);
+        assertEquals(ColumnType.STRING, table.getColumns().get(0).getType());
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(6).getType());
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(7).getType());
+    }
+
+    public void testDetectingDataTypeNotSkippingLinesAndColumnsNoNameLine() {
+        final ExcelDataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/skipped_lines.xlsx"),
+                new ExcelConfiguration(ExcelConfiguration.NO_COLUMN_NAME_LINE, null, false, false, true, 3));
+        final Table table = dataContext.getDefaultSchema().getTables().get(0);
+        assertEquals(ColumnType.STRING, table.getColumns().get(0).getType());
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(6).getType());
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(7).getType());
+    }
+
+    public void testDetectingDataTypeSkippingLinesAndColumnsUsingNameLine() {
+        final ExcelDataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/skipped_lines.xlsx"),
+                new ExcelConfiguration(ExcelConfiguration.DEFAULT_COLUMN_NAME_LINE, null, true, true, true, 3));
+        final Table table = dataContext.getDefaultSchema().getTables().get(0);
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(0).getType());
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(1).getType());
+    }
+
+    public void testDetectingDataTypeSkippingLinesAndColumnsNoNameLine() {
+        final ExcelDataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/skipped_lines.xlsx"),
+                new ExcelConfiguration(ExcelConfiguration.NO_COLUMN_NAME_LINE, null, true, true, true, 3));
+        final Table table = dataContext.getDefaultSchema().getTables().get(0);
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(0).getType());
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(1).getType());
+    }
+
+    public void testToMuchNumberOfLinesToScan() throws Exception {
+        final ExcelDataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/skipped_lines.xlsx"),
+                new ExcelConfiguration(ExcelConfiguration.DEFAULT_COLUMN_NAME_LINE, null, true, true, true, 4));
+
+        final Table table = dataContext.getDefaultSchema().getTables().get(0);
+        assertEquals("hello", table.getColumns().get(0).getName());
+        assertEquals("world", table.getColumns().get(1).getName());
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(0).getType());
+        assertEquals(ColumnType.INTEGER, table.getColumns().get(1).getType());
+        final DataSet dataSet = dataContext.query().from(table).selectCount().execute();
+        assertTrue(dataSet.next());
+        assertEquals(3L, dataSet.getRow().getValue(0));
+    }
+
+    public void testToMissingValueDoesntEffectDetectedType() throws Exception {
+        final ExcelDataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/xls_missing_values.xls"),
+                new ExcelConfiguration(ExcelConfiguration.DEFAULT_COLUMN_NAME_LINE, null, true, false, true, 3));
+
+        final Table table = dataContext.getDefaultSchema().getTables().get(0);
+        final Column columnB = table.getColumns().get(1);
+        assertEquals("b", columnB.getName());
+        assertEquals(ColumnType.INTEGER, columnB.getType());
+        final DataSet dataSetColumnB = dataContext.query().from(table).select(columnB).execute();
+        assertTrue(dataSetColumnB.next());
+        assertTrue(dataSetColumnB.next());
+        assertNull(dataSetColumnB.getRow().getValue(0));
+
+        final Column columnD = table.getColumns().get(3);
+        assertEquals("d", columnD.getName());
+        assertEquals(ColumnType.INTEGER, columnD.getType());
+        final DataSet dataSetColumnD = dataContext.query().from(table).select(columnD).where(columnD).eq(12).execute();
+        assertTrue(dataSetColumnD.next());
+        assertEquals(12, dataSetColumnD.getRow().getValue(0));
+    }
+
+    public void testInsertingValueOfValidColumnType() {
+        final ExcelDataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/different_datatypes.xls"),
+                new ExcelConfiguration(ExcelConfiguration.DEFAULT_COLUMN_NAME_LINE, null, true, false, true, 19));
+        final Table table = dataContext.getDefaultSchema().getTable(0);
+        dataContext.executeUpdate(new InsertInto(table).value("INTEGER", 123));
+        final DataSet dataSet = dataContext.query().from(table).selectAll().where("INTEGER").eq(123).execute();
+        assertTrue(dataSet.next());
+    }
+
+    @Test(expected = MetaModelException.class)
+    public void testInsertingValueOfInvalidColumnType() {
+        final ExcelDataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/different_datatypes.xls"),
+                new ExcelConfiguration(ExcelConfiguration.DEFAULT_COLUMN_NAME_LINE, null, true, false, true, 19));
+        final Table table = dataContext.getDefaultSchema().getTable(0);
+        dataContext.executeUpdate(new InsertInto(table).value("INTEGER", "this is not an integer"));
+    }
+
+    public void testUpdatingValueOfValidColumnType() {
+        final ExcelDataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/different_datatypes.xls"),
+                new ExcelConfiguration(ExcelConfiguration.DEFAULT_COLUMN_NAME_LINE, null, true, false, true, 19));
+        final Table table = dataContext.getDefaultSchema().getTable(0);
+        dataContext.executeUpdate(new Update(table).value("INTEGER", 1).value("INTEGER", 123));
+        final DataSet dataSet = dataContext.query().from(table).selectAll().where("INTEGER").eq(123).execute();
+        assertTrue(dataSet.next());
+    }
+
+    @Test(expected = MetaModelException.class)
+    public void testUpdatingValueOfInvalidColumnType() {
+        final ExcelDataContext dataContext = new ExcelDataContext(copyOf("src/test/resources/different_datatypes.xls"),
+                new ExcelConfiguration(ExcelConfiguration.DEFAULT_COLUMN_NAME_LINE, null, true, false, true, 19));
+        final Table table = dataContext.getDefaultSchema().getTable(0);
+        dataContext.executeUpdate(new Update(table).value("INTEGER", 1).value("INTEGER", "this is not an integer"));
+    }
 }
\ No newline at end of file
diff --git a/excel/src/test/resources/different_datatypes.xls b/excel/src/test/resources/different_datatypes.xls
new file mode 100644
index 0000000..1cdb28e
--- /dev/null
+++ b/excel/src/test/resources/different_datatypes.xls
Binary files differ
diff --git a/excel/src/test/resources/different_datatypes.xlsx b/excel/src/test/resources/different_datatypes.xlsx
new file mode 100644
index 0000000..a7be4d0
--- /dev/null
+++ b/excel/src/test/resources/different_datatypes.xlsx
Binary files differ