diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7a05ed7461d24d83091e92d63b13794a47157642..6d504fb6f588a40a4614cc84a11f5b4023158083 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -34,7 +34,6 @@ run_test:
         - apt-get update -q -y
         - apt-get install wget gnupg -y
         - echo "deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main" > /etc/apt/sources.list.d/pgdg.list
-        - wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
         - apt-get update -q -y
         - apt-get install -y postgresql-client-10
         - yarn install --frozen-lockfile --silent --non-interactive
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4bb554c7693462d23e9fa1c6a6bd37adddd3eaa4..6119d2bb4ac90d3e736119f962423790e53bbe9f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,120 +1,160 @@
 # Changelog
+
 All notable changes to this project will be documented in this file.
 
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## 1.3.0 - 08/10/2021
+
+## Added
+
+- New object type (Table) added #81 (Samuel Leite)
+- Added tests related to Table object.
 
+## Changed
+
+- Changed query methods to account for Table.
 
 ## 1.2.7 - 13/10/2020
+
 ## Added
-- Property times added to form table #80 (Richard Heise)
 
+- Property times added to form table #80 (Richard Heise)
 
 ## 1.2.6 - 19/06/2020
+
 ## Added
-- A extra function on optHandler to better handle form edits #77 (Richard Heise)
 
+- A extra function on optHandler to better handle form edits #77 (Richard Heise)
 
 ## 1.2.5 - 02/06/2020
+
 ## Changed
+
 - Route to list forms now returns all the dates and answers of the forms #75 (Richard Heise)
 - Added two extras steps on route waterfall using eachSeries.
 - Tests weren't changed since the steps where tested by themselfs in other routes.
 
-
 ## 1.2.4 - 01/06/2020
+
 ## Added
+
 - Created route to get modified dates of a form #76 (Richard Heise)
 - Created methods to communicate with the DB
 
-
 ## 1.2.3 - 29/04/2020
-## Changed 
+
+## Changed
+
 - Api to create a subform input without needing input ID from body #73 (Richard Heise)
 - OptHandler to not return error when there's no input ID
 - Subform in core/ to have an optional input ID
 
-
 ## 1.2.2 - 07-04-2020
-## Added 
-- Route to return the number of answers in a form #72 (Richard Heise)
 
+## Added
+
+- Route to return the number of answers in a form #72 (Richard Heise)
 
 ## 1.2.1 - 05-03-2020
+
 ## Added
+
 - Cors to integrate front-end with back-end #68 (Richard Heise)
+
 ### Changed
+
 - Minor route order changes on main.ts to make it more intuitive
 - Port on config.env from 3000 to 3333 for integration purpose
 
-
 ## 1.2.0 - 19-02-2020
+
 ### Changed
-- Created a stable version with user
 
+- Created a stable version with user
 
 ## 1.1.13 - 10-02-2020
+
 ### Added
+
 - Route to read Form Answer #66 (Richard Heise & Gianfranco)
 - Method to get IDs from form answers from a form
 - Read all answers from a form
 - Scenario form test to read
 
-
 ## 1.1.12 - 04-02-2020
+
 ### Added
+
 - Route to update an user #65 (Richard Heise)
-## Changed 
+
+## Changed
+
 - Opthandler can create user without hash
 - UserQueryBuilder Update now needs an id
 - UserOptions hash is not obrigatory
 
-
 ## 1.1.11 - 04-02-2020
+
 ## Changed
-- Form controller update route to verify if a user own the form #62 (Gianfranco)
 
+- Form controller update route to verify if a user own the form #62 (Gianfranco)
 
 ## 1.1.10 - 03-02-2020
+
 ### Added
+
 - Route to list forms #61 (Richard Heise)
+
 ## Changed
-- List from FormQueryBuilder now lists an user's forms
 
+- List from FormQueryBuilder now lists an user's forms
 
 ## 1.1.9 - 03-02-2020
+
 ### Added
+
 - Route to change an user's password #63 (Richard Heise)
+
 ## Changed
-- Delete route now has the token validation
 
+- Delete route now has the token validation
 
 ## 1.1.8 - 30-01-2020
+
 ### Added
+
 - Route to assign users to forms #60 (Richard Heise)
+
 ## Changed
+
 - Route to write a form now has an extra stage in the waterfall
 - This stage assigns the user to a form by ID
 
-
 ## 1.1.7 - 29-01-2020
+
 ### Added
+
 - Function to assign users to forms #54 (Gianfranco)
 - Assign added to userQueryBuilder file
 
-
 ## 1.1.6 - 24-01-2020
+
 ### Added
+
 - Middleware to validate tokens #56 (Richard Heise)
 - Route do delete an user #59 (Richard Heise)
 - Delete control methods on UserQueryBuilder
+
 ## Changed
-- Initial user tests are now on the form.spec.ts
 
+- Initial user tests are now on the form.spec.ts
 
 ## 1.1.5 - 22-01-2020
+
 ### Added
+
 - SubForm class #57 (Gianfranco)
 - InputType SubForm
 - FormQueryBuilder methods to handle with SubForms
@@ -122,179 +162,224 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - OptHandler method to validate SubForm
 - TestHandler method to compare two SubForms
 - Database table for SubForms
+
 ## Changed
+
 - Input class to contain a SubForm object
 - OptHandler methods to handle SubForms Answers
 - Scenario file with new objects to test SubForms
 - TestHandler method to compare two SubFormsAnswer
 
-
 ## 1.1.4 - 19-12-2019
+
 ### Added
+
 - SignIn route to possibilitate logins #55 (Richard Heise)
 - JWT (Json Web Token) library and its types to dependencies
 - Tokens can be created once an user is considered valid
+
 ## Changed
+
 - UserQueryBuilder has, now, a public function to verify if an email is in the DB
 - The requires are now imports for padronization reasons
 
-
 ## 1.1.3 - 12-12-2019
+
 ### Added
+
 - UserCtrl class created to control the user routes #52 (Richard Heise)
 - The bcrypt library and its types to dependencies
 - User route tests
+
 ### Changed
-- User Query Builder now has writeController to validate an unique email user in the database
 
+- User Query Builder now has writeController to validate an unique email user in the database
 
 ## 1.1.2 - 25-11-2019
+
 ### Added
+
 - User class to create an user object #53 (Richard Heise)
 - User Query Builder to write, read and update an user in the database
 - User tests
 - An user table in the database
 
-
 ## 1.1.1 - 17-10-2019
+
 ### Added
+
 - Fixture class to manage the database #49 (Gianfranco)
 - Database module inside the api
 - Before test to call fixture class
+
 ### Changed
+
 - Database to work with usql-manager
 - Config class to receive the new parameters
 
-
 ## 1.1.0 - 11-10-2019
+
 ### Changed
-- Create a stable version
 
+- Create a stable version
 
 ## 1.0.10 - 10-10-2019
+
 ### Added
+
 - Validation type DEPENDENCY #41 (Gianfranco)
+
 ### Changed
-- ValidateInput method to receive a vector of inputs
 
+- ValidateInput method to receive a vector of inputs
 
 ## 1.0.9 - 09-10-2019
+
 ### Added
-- Validation type MAXANSWERS #38 (Gianfranco)
 
+- Validation type MAXANSWERS #38 (Gianfranco)
 
 ## 1.0.8 - 08-10-2019
+
 ### Added
+
 - Validation type SOMECHECKBOX #39 (Gianfranco)
+
 ### Changed
-- ValidateInput method to receive a vector of input answers
 
+- ValidateInput method to receive a vector of input answers
 
 ## 1.0.7 - 01-10-2019
+
 ### Added
-- Validation type TYPEOF #37 (Gianfranco)
 
+- Validation type TYPEOF #37 (Gianfranco)
 
 ## 1.0.6 - 30-09-2019
+
 ### Added
+
 - QueryBuilder Class #47 (Gianfranco)
 - FormQueryBuilder Class #47
 - AnswerQueryBuilder Class #47
+
 ### Changed
-- DbHandler to only have database connections
 
+- DbHandler to only have database connections
 
 ## 1.0.5 - 27-09-2019
+
 ### Added
-- Input type Select #36 (Gianfranco)
 
+- Input type Select #36 (Gianfranco)
 
 ## 1.0.4 - 26-09-2019
+
 ### Added
-- Input type Radio #35 (Gianfranco)
 
+- Input type Radio #35 (Gianfranco)
 
 ## 1.0.3 - 24-09-2019
+
 ### Changed
+
 - Refactor DbHandler #46 (Gianfranco)
 - Fix api routes
 - Set false to max-classes-per-file on tslint
 
-
 ## 1.0.2 - 27-08-2019
+
 ### Added
+
 - Input type Checkbox #34 (Gianfranco)
 - Sugestions for input answers
+
 ### Changed
+
 - OptHandler to validate Sugestions
 - DbHandler to insert Sugestions on database
 
-
 ## 1.0.1 - 20-08-2019
+
 ### Added
+
 - DbHandler methods to update form table #42 (Gianfranco)
+
 ### Changed
+
 - FormUpdate to receive a options changed
 - DiffHandler to recognize changes on forms
 
-
 ## 1.0.0 - 19-08-2019
+
 ### Changed
-- Create a stable version
 
+- Create a stable version
 
 ## 0.0.27 - 15-08-2019
+
 ### Added
+
 - DbHandler methods to update database #32 (Gianfranco)
 - Reenabled UpdateType on EnumHandler wich reenabled a input
 - Update route tests
+
 ### Changed
+
 - writeInputWithFormId method to return the id
 - readInputWithFormId to not list the disabled inputs
 - Fix tests of DiffHandler and DbHandler class
 - DiffHandler to detect reenabled requests
 - Update route to call the updateDatabase method
 
-
 ## 0.0.26 - 26-07-2019
+
 ### Changed
+
 - Write form route to create a formUpdate on create a new form #33 (Gianfranco)
 - Fix DiffHandler to add inputs with id
 - Fix tests of DiffHandler, OptHandler and Form route
 
-
 ## 0.0.25 - 25-07-2019
+
 ### Changed
-- Renamed routes from 'forms' to 'form' #31 (Gianfranco)
 
+- Renamed routes from 'forms' to 'form' #31 (Gianfranco)
 
 ## 0.0.24 - 23-07-2019
+
 ### Added
+
 - DiffHandler to find out the differences between two forms (Gianfranco)
 - Sorter with methods to sort arrays
 - DiffHandler and Sorter tests
+
 ### Changed
+
 - Main archive to add an update route #27
 - Api controller to update forms
 - TestHandler to test two FormUpdate objects
 
-
 ## 0.0.23 - 10-07-2019
+
 ### Changed
+
 - FormUpdate to receive an Form class (Gianfranco)
 - InputUpdate to receive an Input class
 - FormUpdate to receive an array of inputs
 - OptHandler to handle with the new features
 
-
 ## 0.0.22 - 09-07-2019
+
 ### Added
+
 - Created a new enum UpdateType (Gianfranco)
 - Add stringfy and parse methods to UpdateType
 
-
 ## 0.0.21 - 01-07-2019
+
 ### Added
+
 - Add InputUpdate and a FormUpdate Class to store updates from inputs and forms #26 (Gianfranco)
 - Create writeFormUpdate method to insert a FormUpdate into database
 - Create writeInputUpdate method to insert a InputUpdate into database
@@ -302,97 +387,126 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Create inputUpdate method in OptHandler
 - Create formUpdate method in OptHandler
 
-
 ## 0.0.20 - 28-06-2019
+
 ## Changed
-- Class Input to receive a Enabled atribute (Gianfranco)
 
+- Class Input to receive a Enabled atribute (Gianfranco)
 
 ## 0.0.19 - 12-06-2019
+
 ### Added
+
 - A route to POST a form Answer #21 (Horstmann)
 - Create ValidationError Class that extends error class, with the objective to return a dictionary of invalid answers (Horstmann)
+
 ### Changed
+
 - DbHandler's tests to suite with new forms answers added (Horstmann)
 - ValidationHandler to validate a Forms Answer instead of inputsAnswer
 - ValidationHandler's tests to suite new method to validate a Forms Answer
 
-
 ## 0.0.18 - 25-05-2019
+
 ### Added
+
 - Create readFormAnswer method to read formAnswer from database #24 (Horstmann)
 - Create writeFormAnswer method to insert formAnswer into database #24 (Horstmann)
 - Create TestHandler to tests FormAnswers
+
 ### Changed
-- Fix OptHandler to return id in inputAnswer
 
+- Fix OptHandler to return id in inputAnswer
 
 ## 0.0.17 - 25-05-2019
+
 ### Added
+
 - inputAnswer method in OptHandler #23 (Horstmann)
 - formAnswer method in OptHandler #23 (Horstmann)
 
 ### Changed
--  FormsAnswer class to have an dictionary of InputsAnswer
--  FormsAnswer's constructor to use dictionary
 
+- FormsAnswer class to have an dictionary of InputsAnswer
+- FormsAnswer's constructor to use dictionary
 
 ## 0.0.16 - 06-05-2019
+
 ### Added
+
 - A FormsAnswer Class to store answers from forms #22 (Horstmann)
 - A inputsAnswer Class to be the answer for each input in form #22 (Horstmann)
+
 ### Changed
--  Form's  constructor documentation
--  Input's  constructor documentation
 
+- Form's constructor documentation
+- Input's constructor documentation
 
 ## 0.0.15 - 26-04-2019
+
 ### Added
+
 - A QueryOptions interface, that is used on dbHandler's executeQuery #20
+
 ### Changed
--  dbHandler's tests to fit into new interface
+
+- dbHandler's tests to fit into new interface
+
 ### Security
-- Now dbHandler's executeQuery uses parametrized query to avoid SQL injection
 
+- Now dbHandler's executeQuery uses parametrized query to avoid SQL injection
 
 ## 0.0.14 - 26-04-2019
+
 ### Removed
-- Dummies files as Item and Collection #16 (Horstmann)
 
+- Dummies files as Item and Collection #16 (Horstmann)
 
 ## 0.0.13 - 26-04-2019
+
 ### Added
+
 - A route to POST a form #10 (Horstmann)
 - Tests on route POST (Horstmann)
+
 ### Changed
-- dbHandler's tests to suit with new forms and inputs insertion
 
+- dbHandler's tests to suit with new forms and inputs insertion
 
 ## 0.0.12 - 25-04-2019
+
 ### Added
+
 - OptHandler to standardize constructors from Forms and Inputs #19 (Horstmann)
-- InputOptions  interface on class Input #19 (Horstmann)
-- FormOptions  interface on class Form #19 (Horstmann)
+- InputOptions interface on class Input #19 (Horstmann)
+- FormOptions interface on class Form #19 (Horstmann)
+
 ### Changed
+
 - Tests to adapt to new standard of options
 - dbHandler's readInputValidationWithInputId method to return a InputOptions instead of an input
 - Tests to adapt to new standard of options
 - ErrorHandler to add a new error message
 
-
-
 ## 0.0.11 - 17-04-2019
+
 ### Added
+
 - ErrorHandler to standardize errors message through the project #17 (Horstmann)
+
 ### Changed
+
 - TestHandler documentation title
 - dbHandler tests to use ErrorHandler #18 (Horstmann)
 
-
 ## 0.0.10 - 16-04-2019
+
 ### Added
+
 - TestHandler to test form and inputs #18 (Horstmann)
+
 ### Changed
+
 - controller form tests to use testHandler #18 (Horstmann)
 - controller form to improve code coverage
 - dbHandler tests to use testHandler #18 (Horstmann)
@@ -401,68 +515,88 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - ValidationHandler to cast size to number
 - ValidationHandler tests to use string instead of number as validation arguments
 
-
 ## 0.0.9 - 10-04-2019
+
 ### Added
-- Method read in Form controller to get a Form
 
+- Method read in Form controller to get a Form
 
 ## 0.0.8 - 10-04-2019
+
 ### Changed
+
 - main.ts to remove more dummie class
 - dbHandler to include method listForms
+
 ### Added
-- Form controller and method to list all forms
 
+- Form controller and method to list all forms
 
 ## 0.0.7 - 10-04-2019
+
 ### Changed
+
 - main.ts to include dbHandler Middleware and remove dummie class
+
 ### Added
-- Create dbHandler Middleware to be able to access by routes #15 (Horstmann)
 
+- Create dbHandler Middleware to be able to access by routes #15 (Horstmann)
 
 ## 0.0.6 - 01-04-2019
+
 ### Changed
+
 - Input class to match with database model (Add id and description) (Horstmann)
 - Form class to match with database model (Remove version add description) (Horstmann)
 - enumHandler to remove sides whitespaces (Horstmann)
+
 ### Added
+
 - Create readForm method to read form from database #7 (Horstmann)
 - Create readInput method to read input from database #7 (Horstmann)
 - Create writeForm method to insert form into database (Horstmann)
 - Comments to coverage ignore errors that are not reached on tests.
 
-
 ## 0.0.5 - 19-03-2019
+
 ### Changed
+
 - Remove tslint-stylish from package.json, package is deprecated (Horstmann)
 - Update yarn.lock to avoid vulnerabilities (Horstmann)
 - Update CI file to handle database (Horstmann)
+
 ### Added
+
 - Class config using singleton patern, to centralize all configuration in one module (Horstmann)
 - DbHandler to be a layer between API and database #1 (Horstmann)
 
 ## 0.0.4 - 12-02-2019
+
 ### Added
-- Class Form #3 (Horstmann)
 
+- Class Form #3 (Horstmann)
 
 ## 0.0.3 - 07-02-2019
+
 ### Changed
+
 - Added a new type of enum ValitationType #2 (Horstmann)
+
 ### Added
-- ValidationHandle to valited answer given a input #2 (Horstmann)
 
+- ValidationHandle to valited answer given a input #2 (Horstmann)
 
 ## 0.0.2 - 05-02-2019
+
 ### Added
-- EnunHandler to handle types of inputs #4 (Horstmann)
 
+- EnunHandler to handle types of inputs #4 (Horstmann)
 
 ## 0.0.1 - 04-02-2019
+
 ### Added
-- This CHANGELOG file to hopefully serve as an evolving example of a  standardized open source project CHANGELOG.
+
+- This CHANGELOG file to hopefully serve as an evolving example of a standardized open source project CHANGELOG.
 - CI file to enable Gitlab Continuous Integration.
 - Docker files, as Dockerfile and docker-compose, to make easy development and Deploy #6 (Horstmann).
-- Update Node to 10.* #6 (Horstmann).
+- Update Node to 10.\* #6 (Horstmann).
diff --git a/form-creator-database b/form-creator-database
index ed5adee518fdc089faa39bee67e6aac7dcc91ca9..d378c2e3c5324a90a0a72479ce4be68e5ff65c68 160000
--- a/form-creator-database
+++ b/form-creator-database
@@ -1 +1 @@
-Subproject commit ed5adee518fdc089faa39bee67e6aac7dcc91ca9
+Subproject commit d378c2e3c5324a90a0a72479ce4be68e5ff65c68
diff --git a/package.json b/package.json
index 4fed8033cd69715545f5754a0d7fba26819efd40..6a9befb5617e6a1fa36d0107c4daa2eeccada0f0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "form-creator-api",
-  "version": "1.2.7",
+  "version": "1.3.0",
   "description": "RESTful API used to manage and answer forms.",
   "main": "index.js",
   "scripts": {
diff --git a/src/api/controllers/formAnswer.ts b/src/api/controllers/formAnswer.ts
index dee84f501de0e1b749f68a33995339292eeaf11b..b75b9f8af3114bec6dce3628d53d1ee9638a026b 100644
--- a/src/api/controllers/formAnswer.ts
+++ b/src/api/controllers/formAnswer.ts
@@ -19,15 +19,15 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-import { OptHandler } from "../../utils/optHandler";
-import { InputAnswerOptions, InputAnswerOptionsDict } from "../../core/inputAnswer";
+import { waterfall } from "async";
+import { NextFunction, Response } from "express";
 import { Form, FormOptions } from "../../core/form";
 import { FormAnswer, FormAnswerOptions } from "../../core/formAnswer";
+import { InputAnswerOptions, InputAnswerOptionsDict } from "../../core/inputAnswer";
+import { OptHandler } from "../../utils/optHandler";
 import { ValidationHandler } from "../../utils/validationHandler";
-import { Response, NextFunction } from "express";
 import { Request } from "../apiTypes";
-import { waterfall } from "async";
-const util = require('util');
+const util = require("util");
 
 export class AnswerCtrl {
 
@@ -42,25 +42,27 @@ export class AnswerCtrl {
                 return;
             }
 
-            let inputAnswerOptionsDict: InputAnswerOptionsDict = {}
+            const inputAnswerOptionsDict: InputAnswerOptionsDict = {};
 
             for (const key of Object.keys(req.body)) {
                 inputAnswerOptionsDict[parseInt(key, 10)] = [];
                 for (const i in req.body[key]) {
+                    console.log(req.body[key]);
                     const tmpInputAnswerOption: InputAnswerOptions = {
                         idInput: parseInt(key, 10)
                         , placement: parseInt(i, 10)
                         , value: req.body[key][i]
-                    }
+                    };
                     inputAnswerOptionsDict[parseInt(key, 10)].push(tmpInputAnswerOption);
                 }
             }
+            console.log(inputAnswerOptionsDict);
 
-            let formAnswerOpt: FormAnswerOptions = {
+            const formAnswerOpt: FormAnswerOptions = {
                 form: form
                 , timestamp: new Date(Date.now())
                 , inputsAnswerOptions: inputAnswerOptionsDict
-            }
+            };
 
             try {
                 const formAnswer: FormAnswer = new FormAnswer(OptHandler.formAnswer(formAnswerOpt));
diff --git a/src/core/input.ts b/src/core/input.ts
index 59d161c4e537b12442817f6d2edc5359ec19e00b..1b09886b1bda1f71c44ee589920f37517d58d510 100644
--- a/src/core/input.ts
+++ b/src/core/input.ts
@@ -21,6 +21,7 @@
 
 import { InputType, ValidationType } from "../utils/enumHandler";
 import { SubForm, SubFormOptions } from "./subForm";
+import { Table, TableOptions } from "./table";
 
 /** Parameters used to create a input object. */
 export interface InputOptions {
@@ -42,6 +43,8 @@ export interface InputOptions {
     sugestions?: Sugestion[];
     /** A SubForm object that is a reference to another Form */
     subForm?: SubFormOptions;
+    /** A table object */
+    table?: Table;
 }
 /** Validation contains the type of it, and n arguments to validate if necessary */
 export interface Validation {
@@ -82,6 +85,9 @@ export class Input {
     public readonly sugestions: Sugestion[];
     /** A SubForm object that is a reference to another Form */
     public readonly subForm: SubForm;
+    /** A table object */
+    public table?: Table;
+
     /**
      * Creates a new instance of Input Class
      * @param options - InputOptions instance to create a input.
@@ -108,6 +114,11 @@ export class Input {
         } else {
             this.subForm = null;
         }
+        if (options.table) {
+            this.table = options.table;
+        } else {
+            this.table = null;
+        }
         this.validation = options.validation;
     }
 }
diff --git a/src/core/inputAnswer.ts b/src/core/inputAnswer.ts
index c706e3eba8cf501d1761a4e61dfed3e9a356b4fa..654a56e670970429e343e245f46ed3e022bed0e8 100644
--- a/src/core/inputAnswer.ts
+++ b/src/core/inputAnswer.ts
@@ -21,6 +21,7 @@
 
 import { OptHandler } from "../utils/optHandler";
 import { FormAnswer, FormAnswerOptions } from "./formAnswer";
+import { Table, TableOptions } from "./table";
 
 /** Parameters used to create a input object. */
 export interface InputAnswerOptions {
@@ -31,9 +32,11 @@ export interface InputAnswerOptions {
     /** Place where answers should be (multivalored answers). */
     placement: number;
     /** Input's answer */
-    value: string;
+    value: string | Table;
     /** SubForm's answer */
     subForm?: FormAnswerOptions;
+    /** Table object for answers to table questions */
+    table?: Table;
 }
 
 /** Parameters used to create a dictionary to uses as an collection of InputAnswerOptions Object. */
@@ -59,9 +62,11 @@ export class InputAnswer {
     /** Place where input should be in the form. */
     public readonly placement: number;
     /** Input's Description. */
-    public readonly value: string;
+    public readonly value: string | Table;
     /** SubForm Answer. */
     public readonly subForm: FormAnswer;
+    /** Table object for answers to table questions */
+    public table: Table;
 
     /**
      * Creates a new instance of InputAnswer Class
@@ -73,6 +78,7 @@ export class InputAnswer {
         this.placement = options.placement;
         this.value = options.value;
         this.subForm = options.subForm ? new FormAnswer(OptHandler.formAnswer(options.subForm)) : null;
+        this.table = options.table ? options.table : null;
     }
 
 }
diff --git a/src/core/inputUpdate.spec.ts b/src/core/inputUpdate.spec.ts
index dc7fe8dd6264bdd58698c77ffb59908c0b4d515e..5f4c0a845159ff1e06ec36b66c047347498512e1 100644
--- a/src/core/inputUpdate.spec.ts
+++ b/src/core/inputUpdate.spec.ts
@@ -21,6 +21,7 @@
 
 import { expect } from "chai";
 import { inputUpdateScenario } from "../../test/scenario";
+import { DiffHandler } from "../utils/diffHandler";
 import { InputType, UpdateType, ValidationType } from "../utils/enumHandler";
 import { TestHandler } from "../utils/testHandler";
 import { Input, InputOptions } from "./input";
@@ -31,4 +32,11 @@ describe("InputUpdate", () => {
         TestHandler.testInputUpdate(inputUpdateScenario.resInputUpdate, inputUpdateScenario.expInputUpdate);
         done();
     });
+
+    it("should create a valid inputUpdate which changes the table", (done) => {
+        const resInputUpdate = DiffHandler.diff(inputUpdateScenario.formWithDiffTable1, inputUpdateScenario.formWithTable1);
+
+        TestHandler.testInputUpdate(resInputUpdate.inputUpdates[0], inputUpdateScenario.expInputUpdate2);
+        done();
+    });
 });
diff --git a/src/core/table.ts b/src/core/table.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b173d516e43911e5eb1b246f0e46fcb050972e49
--- /dev/null
+++ b/src/core/table.ts
@@ -0,0 +1,56 @@
+/*
+ * form-creator-api. RESTful API to manage and answer forms.
+ * Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR
+ *
+ * This file is part of form-creator-api.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/** Parameters used to create a form object. */
+export interface TableOptions {
+    /** Unique identifier of a Table instance */
+    id?: number;
+
+    rows: number;
+
+    columns: number;
+
+    matrix: any[][];
+}
+/**
+ * Form Class to manage project's forms
+ */
+export class Table {
+    /** Unique identifier of a Form instance */
+    public readonly id: number;
+    /** Form's title. An human-understandable identifier. Not unique */
+    public readonly rows: number;
+    /** Form Description, as propose */
+    public readonly columns: number;
+    /** Array of input. containing question */
+    public readonly matrix: any[][];
+
+    /**
+     * Creates a new instance of Form Class
+     * @param options - TableOptions instance to create a table.
+     */
+    constructor(options: TableOptions) {
+        this.id = options.id ? options.id : null;
+        this.rows = options.rows;
+        this.columns = options.columns;
+        this.matrix = new Array(this.rows).fill(null).map(() => new Array(this.columns).fill(null));
+        }
+    }
diff --git a/src/utils/answerQueryBuilder.ts b/src/utils/answerQueryBuilder.ts
index 9ec441b28ef7dbe9499be50b383fc575c58c643b..64938b83be8afbfcef1a6c3ebabbce7140ebbdc2 100644
--- a/src/utils/answerQueryBuilder.ts
+++ b/src/utils/answerQueryBuilder.ts
@@ -23,7 +23,10 @@ import { eachSeries, waterfall } from "async";
 import { Pool, QueryResult } from "pg";
 import { Form } from "../core/form";
 import { FormAnswer, FormAnswerOptions } from "../core/formAnswer";
+import { Input } from "../core/input";
 import { InputAnswer, InputAnswerOptions, InputAnswerOptionsDict } from "../core/inputAnswer";
+import { Table, TableOptions } from "../core/table";
+import { InputType } from "./enumHandler";
 import { ErrorHandler } from "./errorHandler";
 import { FormQueryBuilder } from "./formQueryBuilder";
 import { OptHandler } from "./optHandler";
@@ -105,7 +108,9 @@ export class AnswerQueryBuilder extends QueryBuilder {
             (formAnswerId: number, callback: (err: Error, result?: any) => void) => {
                 eachSeries(Object.keys(formAnswer.inputAnswers), (key, outerCallback) => {
                     eachSeries(formAnswer.inputAnswers[parseInt(key, 10)], (inputsAnswer, innerCallback) => {
-                        this.writeInputController(formAnswerId, inputsAnswer, innerCallback);
+                        const inputTmp = formAnswer.form.inputs.find((input) => input.id === inputsAnswer.idInput);
+                        const type: number = inputTmp ? inputTmp.type : InputType.SUBFORM;
+                        this.writeInputController(formAnswerId, inputsAnswer, type, innerCallback);
                     }, (error) => {
                         outerCallback(error);
                     });
@@ -126,13 +131,29 @@ export class AnswerQueryBuilder extends QueryBuilder {
      * @param cb - Callback function which contains the data read.
      * @param cb.err - Error information when the method fails.
      */
-    private writeInputController(formAnswerId: number, inputAnswer: InputAnswer, cb: (err: Error) => void) {
+    private writeInputController(formAnswerId: number, inputAnswer: InputAnswer, inputType: InputType, cb: (err: Error) => void) {
         waterfall([
             (callback: (err: Error, result?: number) => void) => {
-                this.executeWriteInput(formAnswerId, inputAnswer, (err: Error, id?: number) => {
+                /* if (inputType === InputType.TABLE)
+                {
+                    callback(null, id);
+                    return;
+                } */
+                this.executeWriteInput(formAnswerId, inputAnswer, inputType, (err: Error, id?: number) => {
                     callback(err, id);
                 });
             },
+            (inputId: number, callback: (err: Error, id?: number) => void) => {
+                if (inputType !== InputType.TABLE)
+                {
+                    callback(null, inputId);
+                    return;
+                }
+                this.writeTableController(inputId, inputAnswer, (err: Error) => {
+
+                    callback(err, inputId);
+                });
+            },
             (inputId: number, callback: (err: Error) => void) => {
                 this.writeSubFormController(inputAnswer.subForm, inputId, (err: Error) => {
                     callback(err);
@@ -213,7 +234,7 @@ export class AnswerQueryBuilder extends QueryBuilder {
      * @param cb.err - Error information when the method fails.
      * @param cb.result - InputAnswer identifier or null if any error occurs.
      */
-    private executeWriteInput(formAnswerId: number, inputAnswer: InputAnswer, cb: (err: Error, result?: number) => void) {
+    private executeWriteInput(formAnswerId: number, inputAnswer: InputAnswer, inputType: InputType, cb: (err: Error, result?: number) => void) {
         const queryString: string = "INSERT INTO input_answer (id_form_answer, id_input, id_sub_form, value, placement) \
                                      VALUES ( $1, $2, $3, $4, $5 ) \
                                      RETURNING id;";
@@ -223,7 +244,7 @@ export class AnswerQueryBuilder extends QueryBuilder {
                 formAnswerId
                 , inputAnswer.idInput
                 , inputAnswer.subForm ? inputAnswer.subForm.id : null
-                , inputAnswer.value
+                , (inputType !== InputType.TABLE) ? inputAnswer.value : null
                 , inputAnswer.placement
             ]
         };
@@ -443,14 +464,38 @@ export class AnswerQueryBuilder extends QueryBuilder {
                     this.readSubFormController(inputAnswer, inputAnswersOpts, innerCallback);
                 }, () => {
                     const inputsAnswerResults: InputAnswerOptionsDict = {};
-                    for (const i of inputAnswersOpts) {
-                        if (inputsAnswerResults[i["idInput"]]) {
-                            inputsAnswerResults[i["idInput"]].push(i);
-                            inputsAnswerResults[i["idInput"]] = Sorter.sortByPlacement(inputsAnswerResults[i["idInput"]]);
-                        } else {
-                            inputsAnswerResults[i["idInput"]] = [i];
+                    const tableInputAnswers: InputAnswerOptions[] = inputAnswersOpts.filter((obj) => obj.value === null && obj.subForm === null);
+                    const otherInputAnswers: InputAnswerOptions[] = inputAnswersOpts.filter((obj) => obj.value !== null || obj.subForm !== null);
+
+                    eachSeries(tableInputAnswers, (input, anotherCallback) => {
+                        this.executeReadTable(input.id, (error: Error, table?: Table) => {
+                            const inputAnswerTmp: InputAnswerOptions = {
+                                id: input.id
+                                , idInput: input.idInput
+                                , placement: input.placement
+                                , value: table
+                                , subForm: input.subForm
+                            };
+                            otherInputAnswers.push(inputAnswerTmp);
+
+                            anotherCallback(error);
+                        });
+                    }, (e) => {
+                        if (e) {
+                            callback(e, null);
+                            return;
                         }
-                    }
+
+                        for (const i of otherInputAnswers) {
+                            if (inputsAnswerResults[i["idInput"]]) {
+                                inputsAnswerResults[i["idInput"]].push(i);
+                                inputsAnswerResults[i["idInput"]] = Sorter.sortByPlacement(inputsAnswerResults[i["idInput"]]);
+                            } else {
+                                inputsAnswerResults[i["idInput"]] = [i];
+                            }
+                            }
+                        }
+                    );
                     callback(null, inputsAnswerResults);
                 });
             },
@@ -604,4 +649,193 @@ export class AnswerQueryBuilder extends QueryBuilder {
             cb(null, result);
         });
     }
+
+    /**
+     * Asynchronously write a table on database without transactions.
+     * @param answerId - Input identifier which validations are linked to.
+     * @param answer - The input containing the table to be added.
+     * @param cb - Callback function which contains informations about method's execution.
+     * @param cb.err - Error information when the method fails.
+     */
+     private writeTableController(answerId: number, answer: InputAnswer, cb: (err: Error) => void) {
+        let row: number = -1;
+        let column: number;
+
+        waterfall([
+                (callback: (err: Error, tableId: number) => void) => {
+                        this.executeCreateTable (answerId, callback);
+                },
+                (tableId: number, callback: (err: Error) => void) => {
+                        const tableTmp = answer.value as Table;
+                        eachSeries(tableTmp.matrix, (line, outerCallback) => {
+                            column = 0;
+                            row++;
+                            eachSeries(line, (value, innerCallback) => {
+                                this.executeWriteCell(tableId, row, column, value, innerCallback);
+                                column++;
+                            }, (err) => {
+                                outerCallback(err);
+                            });
+                        }, (err) => {
+                            callback(err);
+                        });
+                }
+            ], (err) => {
+                if (err) {
+                    cb(err);
+                    return;
+                }
+                cb(null);
+            });
+    }
+
+    /**
+     * Asynchronously insert or update a table cell on database without transactions.
+     * @param tableId - Id of the table to be changed.
+     * @param row - The cell's row.
+     * @param column - The cell's column.
+     * @param value - The value of the cell.
+     * @param cb - Callback function which contains informations about method's execution.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.result - Form identifier or null if any error occurs.
+     */
+     private executeWriteCell(tableId: number, row: number, column: number, value: string, cb: (err: Error) => void) {
+        const queryString: string = "INSERT INTO tables_answer (table_id, row, column_t, value) \
+                                     VALUES ($1, $2, $3, $4) \
+                                     ON CONFLICT ON CONSTRAINT table_answer_id_row_col \
+                                     DO UPDATE SET (table_id, row, column_t, value, enabled) = ($1, $2, $3, $4, true);";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                tableId
+                , row
+                , column
+                , value
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            if (err) {
+                cb(err);
+                return;
+            }
+            cb(null);
+        });
+    }
+
+    /**
+     * Asynchronously create a table on database without transactions.
+     * @param answerId - Answer that has a table associated.
+     * @param cb - Callback function which contains informations about method's execution.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.result - Form identifier or null if any error occurs.
+     */
+    private executeCreateTable(answerId: number, cb: (err: Error, result?: number) => void) {
+        const queryString: string = "INSERT INTO answer_table (answer_id) \
+                                     VALUES ($1) \
+                                     RETURNING table_id;";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                answerId
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            if (err) {
+                cb(err);
+                return;
+            }
+            cb(null, result.rows[0]["table_id"]);
+        });
+    }
+
+    /**
+     * Asynchronously delete a table cell on database without transactions.
+     * @param tableId - Id of the table to be changed.
+     * @param row - The cell's row.
+     * @param column - The cell's column.
+     * @param cb - Callback function which contains informations about method's execution.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.result - Form identifier or null if any error occurs.
+     */
+     private executeDeleteCell(tableId: number, row: number, column: number, cb: (err: Error) => void) {
+        const queryString: string = "UPDATE tables_answer SET enabled=false \
+                                     WHERE table_id=$1 AND row=$2 AND column_t=$3;";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                tableId,
+                row,
+                column
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            if (err) {
+                cb(err);
+                return;
+            }
+            cb(null);
+        });
+    }
+
+    /**
+     * Asynchronously read tables from database without transactions.
+     * @param id - Form identifier which inputs are linked to.
+     * @param cb - Callback function which contains the data read.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.result - inputs or null if inputs not exists.
+     */
+    private executeReadTable(id: number, cb: (err: Error, table?: Table) => void) {
+        waterfall([
+            (callback: (err: Error, options: TableOptions) => void) => {
+                const queryString: string = "SELECT t.table_id, COUNT (DISTINCT row) AS row, COUNT (DISTINCT column_t) as column_t \
+                                            FROM tables_answer t  \
+                                            INNER JOIN answer_table i ON t.table_id = i.table_id \
+                                            WHERE i.answer_id=$1 AND t.enabled=true \
+                                            GROUP BY t.table_id;";
+                const query: QueryOptions = {
+                    query: queryString
+                    , parameters: [id]
+                };
+
+                this.executeQuery(query, (err: Error, result?: QueryResult) => {
+                    const tableOptions: TableOptions = {
+                        id: result.rows[0]["table_id"],
+                        rows: parseInt(result.rows[0]["row"], 10),
+                        columns: parseInt(result.rows[0]["column_t"], 10),
+                        matrix: []
+                    };
+                    callback(err, tableOptions);
+                });
+            },
+            (options: TableOptions, callback: (err: Error, table?: Table) => void) => {
+                const queryString: string = "SELECT id, table_id, row, column_t, value \
+                                            FROM tables_answer  \
+                                            WHERE table_id=$1 AND enabled=true ORDER BY id;";
+                const query: QueryOptions = {
+                    query: queryString
+                    , parameters: [options.id]
+                };
+
+                this.executeQuery(query, (err: Error, result?: QueryResult) => {
+                    const table: Table = new Table(options);
+                    for (const row of result.rows) {
+                        const tRow: number = row["row"];
+                        const tColumn: number = row["column_t"];
+                        table.matrix[tRow][tColumn] = row["value"];
+                    }
+                    callback(err, table);
+                });
+            }
+        ], (err, table?: Table) => {
+            if (err) {
+                cb(err);
+                return;
+            }
+            cb(null, table);
+        });
+    }
+
 }
diff --git a/src/utils/dbHandler.spec.ts b/src/utils/dbHandler.spec.ts
index f8e3d6a6db62ce8f7c474c9aca5a50deb15948c3..f33e5d96de06cb995f10d2a8f0b64790bdc5fece 100644
--- a/src/utils/dbHandler.spec.ts
+++ b/src/utils/dbHandler.spec.ts
@@ -149,6 +149,23 @@ describe("Database Handler", () => {
         });
     });
 
+    it("should insert a table cell", (done) => {
+        dbhandler.form.executeQuery(dbHandlerScenario.insertCell, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("INSERT");
+            expect(result.rowCount).to.be.equal(1);
+            done();
+        });
+    });
+
+    it("should remove an existent table cell", (done) => {
+        dbhandler.form.executeQuery(dbHandlerScenario.deleteCell, (err: Error, result?: QueryResult) => {
+            expect(err).to.be.a("null");
+            expect(result.command).to.be.equal("UPDATE");
+            done();
+        });
+    });
+
     it("should select all input validations", (done) => {
         dbhandler.form.executeQuery(dbHandlerScenario.selectInputValidations, (err: Error, result?: QueryResult) => {
             expect(err).to.be.a("null");
@@ -639,4 +656,12 @@ describe("Read and Write on Database", () => {
         done();
     });
 
+    it("should insert an input with table", (done) => {
+        dbhandler.form.write(dbHandlerScenario.formWithTable1, (err: Error, formResult: Form) => {
+            expect(err).to.be.a("null");
+            TestHandler.testForm(dbHandlerScenario.formWithTable1, formResult);
+            done();
+        });
+    });
+
 });
diff --git a/src/utils/diffHandler.ts b/src/utils/diffHandler.ts
index bfc57558165ab5736660d0424558ae2d21697d5e..02c4077c4c7620a40ec5ab9cf45b30dda6b0b5c4 100644
--- a/src/utils/diffHandler.ts
+++ b/src/utils/diffHandler.ts
@@ -23,6 +23,7 @@ import { Form, FormOptions } from "../core/form";
 import { FormUpdate, FormUpdateOptions } from "../core/formUpdate";
 import { Input, InputOptions } from "../core/input";
 import { InputUpdate, InputUpdateOptions } from "../core/inputUpdate";
+import { Table } from "../core/table";
 import { InputType, UpdateType, ValidationType } from "./enumHandler";
 import { Sorter } from "./sorter";
 
@@ -61,6 +62,51 @@ export class DiffHandler {
                 if (sortedNewInputs[j].placement !== sortedOldInputs[i].placement) {
                     formUpdate.inputUpdates.push(DiffHandler.swapInput(sortedNewInputs[j], sortedOldInputs[i]));
                 }
+
+                if (sortedNewInputs[j].type === InputType.TABLE){
+                    let rowsMax: number = sortedOldInputs[i].table.rows;
+                    let columnsMax: number = sortedOldInputs[i].table.columns;
+
+                    if (sortedNewInputs[j].table.rows > rowsMax){
+                        rowsMax = sortedNewInputs[j].table.rows;
+                    }
+                    if (sortedNewInputs[j].table.columns > columnsMax){
+                        columnsMax = sortedNewInputs[j].table.columns;
+                    }
+
+                    const matrixTmp: any[][] = new Array(rowsMax).fill(-1).map(() => new Array(columnsMax).fill(-1));
+
+                    let k: number = 0;
+                    let l: number = 0;
+                    for (k; k < sortedNewInputs[j].table.rows; k++){
+                        l = 0;
+                        for (l; l < sortedNewInputs[j].table.columns; l++){
+                            matrixTmp[k][l] = sortedNewInputs[j].table.matrix[k][l];
+                        }
+                    }
+
+                    const tableTmp: Table = {
+                        id: sortedNewInputs[j].table.id,
+                        rows: rowsMax,
+                        columns: columnsMax,
+                        matrix: matrixTmp
+                    };
+
+                    const inputTmp: Input = {
+                        id: sortedNewInputs[j].id,
+                        placement: sortedNewInputs[j].placement,
+                        description: sortedNewInputs[j].description,
+                        enabled: sortedNewInputs[j].enabled,
+                        question: sortedNewInputs[j].question,
+                        type: sortedNewInputs[j].type,
+                        validation: sortedNewInputs[j].validation,
+                        sugestions: sortedNewInputs[j].sugestions,
+                        subForm: sortedNewInputs[j].subForm,
+                        table: tableTmp
+
+                    };
+                    formUpdate.inputUpdates.push(DiffHandler.tableInput(inputTmp));
+                }
                 j++;
                 i++;
             }
@@ -151,6 +197,21 @@ export class DiffHandler {
         return inputUpdate;
     }
 
+    /**
+     * Create an InputUpdate object which updates an Input that has a table.
+     * @param input - An input that has a table
+     * @returns - An InputUpdate object.
+     */
+    private static tableInput(newInput: Input): InputUpdate {
+
+        const inputUpdate: InputUpdate = {
+            input: newInput
+            , inputOperation: UpdateType.TABLE
+            , value: null
+        };
+        return inputUpdate;
+    }
+
     private static isIdValid(obj: any): boolean {
         return ((obj.id !== null) && (obj.id !== undefined) && (obj.id > 0) && (typeof obj.id === "number"));
     }
diff --git a/src/utils/enumHandler.ts b/src/utils/enumHandler.ts
index 5035452407a1a797f9cb72218345fb3e3062e439..582c37504684abbca8b269848fd6c12e1e5ddcb6 100644
--- a/src/utils/enumHandler.ts
+++ b/src/utils/enumHandler.ts
@@ -29,6 +29,7 @@ export enum InputType {
     RADIO,
     SELECT,
     SUBFORM,
+    TABLE,
     NONE
 }
 
@@ -37,6 +38,7 @@ export enum UpdateType {
     REMOVE,
     SWAP,
     REENABLED,
+    TABLE,
     NONE
 }
 
@@ -86,6 +88,8 @@ export class EnumHandler {
                 return "select";
             case InputType.SUBFORM:
                 return "subform";
+            case InputType.TABLE:
+                return "table";
             default:
                 return  "";
         }
@@ -109,6 +113,8 @@ export class EnumHandler {
                 return InputType.SELECT;
             case "subform":
                 return InputType.SUBFORM;
+            case "table":
+                return InputType.TABLE;
             default:
                 return InputType.NONE;
         }
@@ -185,6 +191,8 @@ export class EnumHandler {
                 return "swap";
             case UpdateType.REENABLED:
                 return "reenabled";
+            case UpdateType.TABLE:
+                return "table";
             default:
                 return  "";
         }
diff --git a/src/utils/formQueryBuilder.ts b/src/utils/formQueryBuilder.ts
index 4d4b7f8425b1a042bb9a0d9f777508b54c2fa0ee..e6a40ab3698db39fbe2a050b4c964ac1c9610134 100644
--- a/src/utils/formQueryBuilder.ts
+++ b/src/utils/formQueryBuilder.ts
@@ -26,6 +26,7 @@ import { FormUpdate, FormUpdateOptions } from "../core/formUpdate";
 import { Input, InputOptions, Sugestion, Validation } from "../core/input";
 import { InputUpdate, InputUpdateOptions } from "../core/inputUpdate";
 import { SubForm } from "../core/subForm";
+import { Table, TableOptions } from "../core/table";
 import { EnumHandler, InputType, UpdateType, ValidationType } from "./enumHandler";
 import { ErrorHandler } from "./errorHandler";
 import { OptHandler } from "./optHandler";
@@ -246,6 +247,7 @@ export class FormQueryBuilder extends QueryBuilder {
                         return;
                     }
 
+                    // console.log("TIPO FORM: ", typeof(result.rows[0]["id"]));
                     const formTmp: Form = new Form({
                         id: result.rows[0]["id"]
                         , title: result.rows[0]["title"]
@@ -329,6 +331,7 @@ export class FormQueryBuilder extends QueryBuilder {
                             , enabled: i["enabled"]
                             , validation: []
                             , sugestions: []
+                            , table: undefined
                             , subForm: undefined
                         };
                         inputArrayTmp.push(new Input(inputTmp));
@@ -393,6 +396,7 @@ export class FormQueryBuilder extends QueryBuilder {
                                         , type: input.type
                                         , validation: input.validation
                                         , sugestions: input.sugestions
+                                        , table: input.table
                                         , subForm: new SubForm({
                                             id: i.id
                                             , inputId: i.id_input
@@ -411,22 +415,46 @@ export class FormQueryBuilder extends QueryBuilder {
                             outerCallback(null, newSubFormInputs);
                         });
                     },
-                    (newSubFormInputs: Input[], anotherCallback: (er: Error, newForm: Form) => void) => {
+                    (newSubFormInputs: Input[], anotherCallback: (er: Error, newTableInputs?: Input[]) => void) => {
                         let inputsTmp = inputs;
                         for (const i of newSubFormInputs) {
                             inputsTmp.push(i);
                         }
-                        inputsTmp = Sorter.sortByPlacement(inputsTmp);
+                        // inputsTmp = Sorter.sortByPlacement(inputsTmp);
+                        const tableInputs: Input[] = inputsTmp.filter((obj) => obj.type === InputType.TABLE);
+                        const otherInputs: Input[] = inputsTmp.filter((obj) => obj.type !== InputType.TABLE);
+
+                        eachSeries(tableInputs, (input, innerCallback) => {
+                            this.executeReadTable(input.id, (error: Error, table?: Table) => {
+                                input.table = table;
+                                // console.log("INPUT C/ TAB: ", input);
+                                innerCallback(error);
+                            });
+                        }, (e) => {
+                            if (e) {
+                                anotherCallback(e, null);
+                                return;
+                            }
+                            inputsTmp = otherInputs;
+                            for (const i of tableInputs) {
+                                inputsTmp.push(i);
+                            }
+                            inputsTmp = Sorter.sortByPlacement(inputsTmp);
+                            anotherCallback(null, inputsTmp);
+                        });
+                    },
+                    (newTableInputs: Input[], tableCallback: (er: Error, form?: Form) => void) => {
 
+                        // console.log("INPUTS TMP: ", newTableInputs);
                         const formTmp: Form = new Form({
                             id: form.id
                             , title: form.title
                             , description: form.description
-                            , inputs: inputsTmp
+                            , inputs: newTableInputs
                             , answerTimes: form.answerTimes
                             , status: form.status
                         });
-                        anotherCallback(null, formTmp);
+                        tableCallback(null, formTmp);
                     }
                 ], (er, formTmp?: Form) => {
                     if (er) {
@@ -505,6 +533,68 @@ export class FormQueryBuilder extends QueryBuilder {
         });
     }
 
+    /**
+     * Asynchronously read tables from database without transactions.
+     * @param id - Form identifier which inputs are linked to.
+     * @param cb - Callback function which contains the data read.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.result - inputs or null if inputs not exists.
+     */
+     private executeReadTable(id: number, cb: (err: Error, table?: Table) => void) {
+        waterfall([
+            (callback: (err: Error, options: TableOptions) => void) => {
+                const queryString: string = "SELECT t.table_id, COUNT (DISTINCT row) AS row, COUNT (DISTINCT column_t) as column_t \
+                                            FROM tables t  \
+                                            INNER JOIN input_table i ON t.table_id = i.table_id \
+                                            WHERE i.input_id=$1 AND t.enabled=true \
+                                            GROUP BY t.table_id;";
+                const query: QueryOptions = {
+                    query: queryString
+                    , parameters: [id]
+                };
+
+                this.executeQuery(query, (err: Error, result?: QueryResult) => {
+                    // console.log("RESULTADO: ", result);
+                    const tableOptions: TableOptions = {
+                        id: result.rows[0]["table_id"],
+                        rows: parseInt(result.rows[0]["row"], 10),
+                        columns: parseInt(result.rows[0]["column_t"], 10),
+                        matrix: []
+                    };
+                    callback(err, tableOptions);
+                });
+            },
+            (options: TableOptions, callback: (err: Error, table?: Table) => void) => {
+                const queryString: string = "SELECT id, table_id, row, column_t, value \
+                                            FROM tables  \
+                                            WHERE table_id=$1 AND enabled=true ORDER BY id;";
+                const query: QueryOptions = {
+                    query: queryString
+                    , parameters: [options.id]
+                };
+
+                this.executeQuery(query, (err: Error, result?: QueryResult) => {
+                    // console.log(options);
+                    const table: Table = new Table(options);
+                    // console.log(table.matrix);
+                    for (const row of result.rows) {
+                        const tRow: number = row["row"];
+                        const tColumn: number = row["column_t"];
+                        table.matrix[tRow][tColumn] = row["value"];
+                    }
+                    // console.log(table.matrix);
+                    callback(err, table);
+                });
+            }
+        ], (err, table?: Table) => {
+            if (err) {
+                cb(err);
+                return;
+            }
+            cb(null, table);
+        });
+    }
+
     /**
      * Asynchronously read validations from database without transactions.
      * @param id - Form identifier which validations from inputs are linked to.
@@ -659,6 +749,11 @@ export class FormQueryBuilder extends QueryBuilder {
             (callback: (err: Error, result?: number) => void) => {
                 this.executeWriteInput(formId, input, callback);
             },
+            (inputId: number, callback: (err: Error, resultInputId?: number) => void) => {
+                this.writeTableController(inputId, input, (error: Error) => {
+                    callback(error, inputId);
+                });
+            },
             (inputId: number, callback: (err: Error, resultInputId?: number) => void) => {
                 this.writeValidationController(inputId, input.validation, (error: Error) => {
                     callback(error, inputId);
@@ -772,6 +867,140 @@ export class FormQueryBuilder extends QueryBuilder {
         });
     }
 
+    /**
+     * Asynchronously write a table on database without transactions.
+     * @param inputId - Input identifier which validations are linked to.
+     * @param input - The input containing the table to be added.
+     * @param cb - Callback function which contains informations about method's execution.
+     * @param cb.err - Error information when the method fails.
+     */
+     private writeTableController(inputId: number, input: Input, cb: (err: Error) => void) {
+        let row: number = -1;
+        let column: number;
+
+        if (input.type !== InputType.TABLE){
+            cb(null);
+            return;
+        } else {
+            waterfall([
+                (callback: (err: Error, tableId: number) => void) => {
+                        this.executeCreateTable (inputId, callback);
+                },
+                (tableId: number, callback: (err: Error) => void) => {
+                        eachSeries(input.table.matrix, (line, outerCallback) => {
+                            column = 0;
+                            row++;
+                            eachSeries(line, (value, innerCallback) => {
+                                this.executeWriteCell(tableId, row, column, value, innerCallback);
+                                column++;
+                            }, (err) => {
+                                outerCallback(err);
+                            });
+                        }, (err) => {
+                            callback(err);
+                        });
+                }
+            ], (err) => {
+                if (err) {
+                    cb(err);
+                    return;
+                }
+                cb(null);
+            });
+        }
+    }
+
+    /**
+     * Asynchronously insert or update a table cell on database without transactions.
+     * @param tableId - Id of the table to be changed.
+     * @param row - The cell's row.
+     * @param column - The cell's column.
+     * @param value - The value of the cell.
+     * @param cb - Callback function which contains informations about method's execution.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.result - Form identifier or null if any error occurs.
+     */
+     private executeWriteCell(tableId: number, row: number, column: number, value: string, cb: (err: Error) => void) {
+        const queryString: string = "INSERT INTO tables (table_id, row, column_t, value) \
+                                     VALUES ($1, $2, $3, $4) \
+                                     ON CONFLICT ON CONSTRAINT table_id_row_col \
+                                     DO UPDATE SET (table_id, row, column_t, value, enabled) = ($1, $2, $3, $4, true);";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                tableId
+                , row
+                , column
+                , value
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            if (err) {
+                cb(err);
+                return;
+            }
+            cb(null);
+        });
+    }
+
+    /**
+     * Asynchronously create a table on database without transactions.
+     * @param inputId - Input that has a table associated.
+     * @param cb - Callback function which contains informations about method's execution.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.result - Form identifier or null if any error occurs.
+     */
+    private executeCreateTable(inputId: number, cb: (err: Error, result?: number) => void) {
+        const queryString: string = "INSERT INTO input_table (input_id) \
+                                     VALUES ($1) \
+                                     RETURNING table_id;";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                inputId
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            if (err) {
+                cb(err);
+                return;
+            }
+            cb(null, result.rows[0]["table_id"]);
+        });
+    }
+
+    /**
+     * Asynchronously delete a table cell on database without transactions.
+     * @param tableId - Id of the table to be changed.
+     * @param row - The cell's row.
+     * @param column - The cell's column.
+     * @param cb - Callback function which contains informations about method's execution.
+     * @param cb.err - Error information when the method fails.
+     * @param cb.result - Form identifier or null if any error occurs.
+     */
+     private executeDeleteCell(tableId: number, row: number, column: number, cb: (err: Error) => void) {
+        const queryString: string = "UPDATE tables SET enabled=false \
+                                     WHERE table_id=$1 AND row=$2 AND column_t=$3;";
+        const query: QueryOptions = {
+            query: queryString
+            , parameters: [
+                tableId,
+                row,
+                column
+            ]
+        };
+
+        this.executeQuery(query, (err: Error, result?: QueryResult) => {
+            if (err) {
+                cb(err);
+                return;
+            }
+            cb(null);
+        });
+    }
+
     /**
      * Asynchronously insert a form on database without transactions.
      * @param form - Form to be inserted.
@@ -1185,6 +1414,28 @@ export class FormQueryBuilder extends QueryBuilder {
                     });
                     break;
                 }
+                case UpdateType.TABLE: {
+                    let row: number = -1;
+                    let column: number;
+
+                    eachSeries(inputUpdate.input.table.matrix, (line, outerCallback) => {
+                        column = 0;
+                        row++;
+                        eachSeries(line, (value, innerCallback) => {
+                            if (value !== -1){
+                                this.executeWriteCell(inputUpdate.input.table.id, row, column, value, innerCallback);
+                            } else {
+                                this.executeDeleteCell(inputUpdate.input.table.id, row, column, innerCallback);
+                            }
+                            column++;
+                        }, (err) => {
+                            outerCallback(err);
+                        });
+                    }, (err) => {
+                        callback(err);
+                    });
+                    break;
+                }
                 default: {
                     callback(new Error("Operation " + inputUpdate.inputOperation + " not recognized"));
                     break;
diff --git a/src/utils/optHandler.ts b/src/utils/optHandler.ts
index c6dd1a962c4195f8efda393aa5a9b459c7c18e05..00cc606cf07a109f654f71f9dfc2ce2626add7ce 100644
--- a/src/utils/optHandler.ts
+++ b/src/utils/optHandler.ts
@@ -26,6 +26,7 @@ import { InputOptions, Sugestion, Validation } from "../core/input";
 import { InputAnswer, InputAnswerDict, InputAnswerOptions, InputAnswerOptionsDict } from "../core/inputAnswer";
 import { InputUpdate, InputUpdateOptions } from "../core/inputUpdate";
 import { SubForm, SubFormOptions } from "../core/subForm";
+import { Table } from "../core/table";
 import { User, UserOptions } from "./../core/user";
 import { InputType, UpdateType } from "./enumHandler";
 import { ErrorHandler } from "./errorHandler";
@@ -87,6 +88,9 @@ export class OptHandler {
         if ((obj.type === InputType.SUBFORM) && ((obj.subForm === undefined) || (obj.subForm === null))) {
             throw ErrorHandler.notFound("Input subform");
         }
+        if ((obj.type === InputType.TABLE) && ((obj.table === undefined) || (obj.table === null))) {
+            throw ErrorHandler.notFound("Input table");
+        }
 
         let subForm: SubForm = null;
         if ((obj.subForm !== null) && (obj.subForm !== undefined)) {
@@ -104,6 +108,7 @@ export class OptHandler {
                 return { type: v.type, arguments: v.arguments };
             }),
             sugestions: [],
+            table: obj.table,
             subForm
         };
 
@@ -333,4 +338,26 @@ export class OptHandler {
         return option;
 
     }
+
+    public static table(obj: any): Table {
+
+        if (obj.id === undefined) {
+            throw ErrorHandler.notFound("Table id");
+        }
+        if (obj.rows === undefined) {
+            throw ErrorHandler.notFound("Table row count");
+        }
+        if (obj.columns === undefined) {
+            throw ErrorHandler.notFound("Table columns count");
+        }
+
+        const option: Table = {
+            id: obj.id
+            , rows: obj.rows
+            , columns: obj.columns
+            , matrix: [[]]
+        };
+
+        return option;
+    }
 }
diff --git a/src/utils/testHandler.ts b/src/utils/testHandler.ts
index 3666abc9c36b14dd5d0444d7295c9cc9b65eadb4..c92b4f08433bfa8b40239b9eaf0aebac3f7acde3 100644
--- a/src/utils/testHandler.ts
+++ b/src/utils/testHandler.ts
@@ -27,6 +27,7 @@ import { Input, Validation } from "../core/input";
 import { InputAnswer } from "../core/inputAnswer";
 import { InputUpdate } from "../core/inputUpdate";
 import { SubForm } from "../core/subForm";
+import { Table } from "../core/table";
 import { User } from "../core/user";
 import { EnumHandler, InputType, UpdateType, ValidationType } from "./enumHandler";
 import { Sorter } from "./sorter";
@@ -79,6 +80,10 @@ export class TestHandler {
         } else {
             expect(input.subForm).to.be.equal(null);
         }
+
+        if (input.type === InputType.TABLE) {
+            TestHandler.testTable(input.table, stub.table);
+        }
     }
 
     /**
@@ -168,4 +173,21 @@ export class TestHandler {
         expect(subForm.inputId).to.be.equal(stub.inputId);
         expect(subForm.contentFormId).to.be.equal(stub.contentFormId);
     }
+
+    /**
+     * Verify if two tables are semantically equal;
+     * @param table - table that should be tested
+     * @param stub - A model table that first param should be equal to.
+     * @returns - True if tables are equal else false
+     */
+     public static testTable(table: Table, stub: Table) {
+        expect(table.id).to.be.equal(stub.id);
+        expect(table.rows).to.be.equal(stub.rows);
+        expect(table.columns).to.be.equal(stub.columns);
+        for (let r = 0; r < table.rows; r++){
+            for (let c = 0; c < table.columns; c++){
+                expect(table.matrix[r][c]).to.be.equal(stub.matrix[r][c]);
+            }
+        }
+    }
 }
diff --git a/src/utils/validationHandler.ts b/src/utils/validationHandler.ts
index 5d49c0e4a32975b673f68484f4395bcb58b29202..5dcb53eb215269ec2bd09b59686360b06562b69c 100644
--- a/src/utils/validationHandler.ts
+++ b/src/utils/validationHandler.ts
@@ -185,7 +185,7 @@ export class ValidationHandler {
 
                 case ValidationType.REGEX:
                     for (const answer of inputAnswers[input.id]) {
-                        if (!this.validateByRegex(answer.value, validation.arguments[0])) {
+                        if (!this.validateByRegex(answer.value as string, validation.arguments[0])) {
                             errors.push("RegEx do not match");
                         }
                     }
@@ -193,7 +193,7 @@ export class ValidationHandler {
 
                 case ValidationType.MANDATORY:
                     for (const answer of inputAnswers[input.id]) {
-                        if (!(this.validateMandatory(answer.value))) {
+                        if (!(this.validateMandatory(answer.value as string))) {
                             errors.push("Input answer is mandatory");
                         }
                     }
@@ -201,7 +201,7 @@ export class ValidationHandler {
 
                 case ValidationType.MAXCHAR:
                     for (const answer of inputAnswers[input.id]) {
-                        if (!(this.validateMaxChar(answer.value, validation.arguments[0]))) {
+                        if (!(this.validateMaxChar(answer.value as string, validation.arguments[0]))) {
                             errors.push("Input answer must be lower than " + validation.arguments[0]);
                         }
                     }
@@ -209,7 +209,7 @@ export class ValidationHandler {
 
                 case ValidationType.MINCHAR:
                     for (const answer of inputAnswers[input.id]) {
-                        if (!(this.validateMinChar(answer.value, validation.arguments[0]))) {
+                        if (!(this.validateMinChar(answer.value as string, validation.arguments[0]))) {
                             errors.push("Input answer must be greater than " + validation.arguments[0]);
                         }
                     }
@@ -217,7 +217,7 @@ export class ValidationHandler {
 
                 case ValidationType.TYPEOF:
                     for (const answer of inputAnswers[input.id]) {
-                        if (!(this.validateTypeOf(answer.value, validation.arguments[0]))) {
+                        if (!(this.validateTypeOf(answer.value as string, validation.arguments[0]))) {
                             errors.push("Input answer must be a " + validation.arguments[0]) + " type";
                         }
                     }
diff --git a/test/scenario.ts b/test/scenario.ts
index 6763eab961826b9240c60c971b7634bfd0fbefb3..85585dd65ed8cc4bfa7f907fc5210e762ee6e723 100644
--- a/test/scenario.ts
+++ b/test/scenario.ts
@@ -26,6 +26,7 @@ import { Input, InputOptions, Validation } from "../src/core/input";
 import { InputAnswerOptions, InputAnswerOptionsDict } from "../src/core/inputAnswer";
 import { InputUpdate, InputUpdateOptions } from "../src/core/inputUpdate";
 import { SubForm, SubFormOptions } from "../src/core/subForm";
+import { Table, TableOptions } from "../src/core/table";
 import { User } from "../src/core/user";
 import { EnumHandler, InputType, UpdateType, ValidationType } from "../src/utils/enumHandler";
 import { OptHandler } from "../src/utils/optHandler";
@@ -526,6 +527,60 @@ const Input4Placement2id4: Input = {
     , sugestions: []
     , subForm: null
 };
+/* input with table */
+const InputWithTable1: Input = {
+    id: 38
+    , placement: 0
+    , description: "Description Question 1 Form 1"
+    , question: "Question 1 Form 1"
+    , enabled: true
+    , type: InputType.TABLE
+    , validation: []
+    , table: {
+        id: 1,
+        rows: 2,
+        columns: 2,
+        matrix: [["1", "2"], ["3", "4"]]
+    }
+    , sugestions: []
+    , subForm: null
+};
+/* input with table */
+const InputWithDiffTable1: Input = {
+    placement: 0
+    , description: "Description Question 1 Form 1"
+    , question: "Question 1 Form 1"
+    , enabled: true
+    , type: InputType.TABLE
+    , validation: []
+    , id: 38
+    , table: {
+        id: 1,
+        rows: 1,
+        columns: 3,
+        matrix: [["a", "b", "c"]]
+    }
+    , sugestions: []
+    , subForm: null
+};
+/* input with table */
+const InputUpdateTable1: Input = {
+    placement: 0
+    , description: "Description Question 1 Form 1"
+    , question: "Question 1 Form 1"
+    , enabled: true
+    , type: InputType.TABLE
+    , validation: []
+    , id: 38
+    , table: {
+        id: 1,
+        rows: 2,
+        columns: 3,
+        matrix: [["a", "b", "c"], [-1, -1, -1]]
+    }
+    , sugestions: []
+    , subForm: null
+};
 /** input to be compared */
 const mixedInput1: Input = {
     placement: 1
@@ -697,6 +752,28 @@ const formBase3: Form = {
     answerTimes: true
     , status: true
 };
+/** Form with table 1 */
+const formWithTable1: Form = {
+    id: 12
+    , title: "Form Title 1"
+    , description: "Form Description 1"
+    , inputs: [
+        InputWithTable1
+    ],
+    answerTimes: true
+    , status: true
+};
+/** Form with table 1 */
+const formWithDiffTable1: Form = {
+    id: 1
+    , title: "Form Title 1"
+    , description: "Form Description 1"
+    , inputs: [
+        InputWithDiffTable1
+    ],
+    answerTimes: true
+    , status: true
+};
 /** Empty form used as a base for comparison */
 const emptyForm: Form = {
     id: 1
@@ -906,6 +983,11 @@ const expInputUpdate: InputUpdate = {
     , value: null
     , id: null
 };
+const expInputUpdate2: InputUpdate = {
+    input: InputUpdateTable1
+    , inputOperation: UpdateType.TABLE
+    , value: null
+};
 /** ============================================= */
 /** Input testing Scenario */
 
@@ -2142,6 +2224,14 @@ const queryToRemoveInputAnswers: QueryOptions = { query: queryStringRemoveInputA
 const queryStringRemoveForm3: string = "UPDATE form SET status='false' WHERE id=3;";
 /** Query obj to be used to delete form */
 const queryToRemoveForm3: QueryOptions = { query: queryStringRemoveForm3, parameters: [] };
+/** QueryString to be used on a query to add table cell */
+const queryStringInsertCell: string = "INSERT INTO tables (table_id, row, column_t, value) VALUES (0, 0, 0, 'test');";
+/** Query obj to be used to insert cell */
+const queryToInsertCell: QueryOptions = { query: queryStringInsertCell, parameters: [] };
+/** QueryString to be used on a query to add table cell */
+const queryStringDeleteCell: string = "UPDATE tables SET enabled=false WHERE table_id=0 AND row=0 AND column_t=0;";
+/** Query obj to be used to insert cell */
+const queryToDeleteCell: QueryOptions = { query: queryStringDeleteCell, parameters: [] };
 
 /** 2nd describe */
 /** Input Options object to be used on a formOptions */
@@ -2251,14 +2341,14 @@ const inputObjToUpdateDBH3: InputOptions = {
     ]
     , id: 2
 };
-/** InputUpdateOptions object to do an remotion update */
+/** InputUpdateOptions object to do a remotion update */
 const updateObjDBH3REMOVE: InputUpdateOptions = {
     id: 3
     , input: inputObjToUpdateDBH3
     , inputOperation: UpdateType.REMOVE
     , value: null
 };
-/** InputUpdateOptions object to do an reenable update */
+/** InputUpdateOptions object to do a reenable update */
 const updateObjDBH3REENABLE: InputUpdateOptions = {
     id: 3
     , input: inputObjToUpdateDBH3
@@ -3820,7 +3910,13 @@ export const inputUpdateScenario = {
     /** Answer input recieved to update */
     resInputUpdate: resInputUpdate,
     /** Expected input after the update */
-    expInputUpdate: expInputUpdate
+    expInputUpdate: expInputUpdate,
+    /** Input with table 1 */
+    formWithTable1: formWithTable1,
+    /** Input with table 2 */
+    formWithDiffTable1: formWithDiffTable1,
+    /** Expected inputUpdate object */
+    expInputUpdate2: expInputUpdate2
 };
 /** input testing scenario */
 export const inputScenario = {
@@ -4086,6 +4182,10 @@ export const dbHandlerScenario = {
     removeInputAnswers: queryToRemoveInputAnswers,
     /** Query to delete form with id 3 */
     deleteForm3: queryToRemoveForm3,
+    /** Query to insert table cell on the Database */
+    insertCell: queryToInsertCell,
+    /** Query to delete table cell on the Database */
+    deleteCell: queryToDeleteCell,
 
     /** Form options that will have to be read */
     formToRead: formOptsObjDBH,
@@ -4137,6 +4237,8 @@ export const dbHandlerScenario = {
     formUpdateWithSubFormLoop: formUpdateWithSubForm4,
     /** FormAnswer for Form with SubForm */
     formAnswerWithSubForms: formAnswerOptionsForm11,
+    /** Form with a table */
+    formWithTable1: formWithTable1,
 
     /** User obj to be inserted */
     toBeInserted: defaultUser,