Knowledge Base
  • Introduction
  • Events and Actions
  • Action Panel
  • sending email
  • calling a SQL action from a client side js action
  • Accessing to translations form a server
  • Executing SQL statements from within an action
  • How to invoke a generic SQL statement defined through a SQL action
  • How to show a message dialog
  • checking for "undefined" values
  • How to add spaces to the right of a text
  • How to create a docx report and show it on the web browser Enterprise Edition only
  • How to get or set a value from the graphics control
  • How to invoke a generic SQL query defined through a business component
  • How to remove spaces to the left and right of a text
  • How to support multiple themes in a single application, accoding to a rule
  • How to set content to a Google Map linked to a grid or form
  • How to replace all occurences of a pattern from a text
  • Utility methods
  • Link auto login
  • Creation of a link for the first access of a new user without give the user a password and forcing
  • Forgot password
  • setting up default values from values coming from a filter panel
  • identifing the modified record after the alteration
  • enabling/disabling checkboxes in a grid
  • Filtering a Lookup
  • formatting a column
  • using checkboxes to select rows in grid
  • showing a summary row in grid
  • Disabling a toolbar button
  • Configuring grid exports
  • Adding filter conditions to a grid
  • Filtering the grid content from a tree
  • Filtering the tree content, starting from a filter panel linked to a grid
  • collapsing a panel
  • validating a lookup
  • accessing the authorizations set for a specific grid
  • How to design a web service
  • How to remotelly invoke an action or business component or perform a write operation through a Restf
  • how to feed a grid from a JS business component
  • converting a JS object to a JSON string
  • executing a query
  • passing parameters to a server side JS action
  • return value
  • scheduling and frequency
  • finding the right filter panel
  • checking out if a component has been defined
  • Deploying an application
  • Enquiring a table belonging to the Platform repository
  • Adding a where clause to a business component linked to grid
  • Integrating Mailchimp lists
  • Formatting a number as a currency value to use it inside an email template
  • sending email from a template
  • How to send an email
  • Error 'smtpHost' is empty
  • Linking two windows
  • How to open manually a window from another window
  • How to open manually a popup window
  • How to hide a panel in a window dinamically
  • How to manage folder panels
  • How to manage card panels
  • Predefined variables supported by Platform
  • Accessing the application parameters
  • Application Log
  • How to design a web service
  • How to import java classes in server
  • How to import java classes in server
  • How to dynamically set a value on a combo
  • 4WS.Platform
  • How to listen to events in a mobile HTML panel
  • Issues with HTTPS requests
  • How to manage row totals in grid
  • How to send to the UI a notification to execute code automatically
  • How to filter a chart by date interval
  • How to filter a grid by date interval
  • How to read a text or csv file and save data on the database
  • How to write text or csv files
  • Reading an xls file stored in the specified path
  • How to create a report with Jasper Report
  • How to customize the alert message content
  • Setting up a cluster
  • Uploading and downloading files
  • How to listen to user definition changes
  • How to auto-show a window from login
  • How to manage encrypted fields
  • How to change CSS settings for a grid row
  • Customizing a Tree Panel
  • How to execute complex queries on Google Datastore
  • Theme customization
  • Retrieve and send the log of a mobile app
  • Import Roles and Users
  • How to synchronize multiple Form panels in the same window
  • Anchor buttons
  • Properties of subpanels
  • Bulk import
  • How to display the data not found message in a grid
  • How to setup an LDAP based authentication
  • How to synchronize data from Datastore to BigQuery
  • How to synchronize data from Datastore to Google Spanner
  • How to synchronize data from Datastore to CloudSQL
  • Scrollable form list
  • How to setup SAML authentication
  • How to export data from BigQuery in streaming
  • Update Google Spreadsheet
  • How to setup OAuth2 authentication
Powered by GitBook
On this page
  • Reading a CSV file
  • Reading a text file
  • How to write data in a database
  • Optimizing csv reading and data loading on a single table

Was this helpful?

How to read a text or csv file and save data on the database

Platform provides 2 distinct utility methods in a server-side javascript action to read a text file:

  • read a CSV file

  • read a generic text file, whose content is not clearly delimited by a special symbol (like for a CSV file)

In both cases, the best approach is reading the file content line by line: in this way, there will not be a memory consumption due to the file size, since only one line is read a time.

In order to do it, a callback function must be defined: it will be automatically invoked by the utility method for each line and the whole line will be passed forward to such a callback function.

Within this callback function it is possible to save data in the database. Again, there are different ways to do it, in order to manage whether the writing operation must be an INSERT or an UPDATE.

One way to do it, is by executing first a SELECT, in order to figure out if the record already exists; after that, an INSERT or UPDATE operation can be carried out.

Reading a CSV file

Example: suppose you have a comma (,) separated CSV file having 3 fields: persone code, first name, last name.

var myCallbackFunction = function(obj) { 
  // obj is a javascript object containing a line read from the CSV file, having the structure:
  // { personCode: "..", firstName: "...", lastName: "..." }

  var json = utils.executeQuery(
    "SELECT PERSON_CODE FROM PEOPLE WHERE PERSON_CODE=? ",
    null,
    false,
    true,
    [obj.personCode]
  );
  var list = JSON.parse(json); // here list is a zero length list in case the specified personCode does not exist in the db

  if (list.length==0) {
    // record does not exist yet: insert it
    utils.executeSql(
      "INSERT INTO PEOPLE(PERSON_CODE,FIRSTNAME,LASTNAME) VALUES(?,?,?) ",
      null, 
      false, 
      true,
      [ obj.personCode, obj.firstName, obj.lastName ]
    );
  }
  else {
    // update record
    utils.executeSql(
      "update PEOPLE set FIRSTNAME=?,LASTNAME=? WHERE PERSON_CODE=? ",
      null, 
      false, 
      true,
      [ obj.firstName, obj.lastName, obj.personCode ]
    );
  }
}

var attributeNames = ["personCode","firstName","lastName"]; 
var directoryId = ... // id for a directory defined in the AppDesigner
var fileName = "..."; // file name for the CSV file saved in the path specified by directory id

utils.readCSVFile(
  fileName,
  directoryId,
  ",", // fields separator: , or ;
  false, // flag used to skip the first line in the CSV file
  "myCallbackFunction",
  attributeNames
);

Reading a text file

Example: suppose you have a text file having 3 fixed length fields: 10 characters for a code, 20 characters for the first name, 20 characters for the last name.

var myCallbackFunction = function(line) { 
  // line is a javascript String containing the whole line just read
  var personCode = line.substring(0,10);
  var firstName = line.substring(10,30);
  var lastName = line.substring(30);

  var json = utils.executeQuery(
    "SELECT PERSON_CODE FROM PEOPLE WHERE PERSON_CODE=? ",
    null, // data source id
    false, // separatedTransaction
    true, // interruptExecution
    [personCode]
  );
  var list = JSON.parse(json); // here list is a zero length list in case the specified personCode does not exist in the db

  if (list.length==0) {
    // record does not exist yet: insert it
    utils.executeSql(
      "INSERT INTO PEOPLE(PERSON_CODE,FIRSTNAME,LASTNAME) VALUES(?,?,?) ",
      null, // data source id
      false, // separatedTransaction
      true, // interruptExecution
      [ personCode, firstName, lastName ]
    );
  }
  else {
    // update record
    utils.executeSql(
      "update PEOPLE set FIRSTNAME=?,LASTNAME=? WHERE PERSON_CODE=? ",
     null, // data source id
      false, // separatedTransaction
      true, // interruptExecution  
      [ firstName, lastName, personCode ]
    );
  }
}

var directoryId = ... // id for a directory defined in the AppDesigner
var fileName = "..."; // file name for the CSV file saved in the path specified by directory id

utils.readTextFile(String fileName,Long directoryId,String callbackFunName,String charset)
  fileName,
  directoryId,
  "myCallbackFunction",
  "UTF-8" // char-set for the text file to read
);

How to write data in a database

Both examples above report a way to write data in a database: using SQL statements through the utils.executeSql utility method.

An alternative way to do it is by defining a Data Model in the App Designer for the table where writing and then use the utils.insertObject or utils.updateObject methods to automate the SQL statement generation.

Example: suppose there is a table named PEOPLE, having 5 fields: PERSON_CODE, FIRST_NAME, LAST_NAME, ENABLED and CREATE_DATE (having datetime field type).

The callback function for the first example (CSV file) would be:

var myCallbackFunction = function(obj) { 

  var json = utils.executeQuery(
    "SELECT PERSON_CODE FROM PEOPLE WHERE PERSON_CODE=? ",
    null, // data source id
    false, // separatedTransaction
    true, // interruptExecution
    [obj.personCode]
  );
  var list = JSON.parse(json); // here list is a zero length list in case the specified personCode does not exist in the db

  obj.enabled: "Y",
  obj.createDate: utils.getCurrentDateAndTime();

  var dataModelId = ... // data model id related to the table PEOPLE

  if (list.length==0) {
    // record does not exist yet: insert it
    utils.insertObject(
      obj,
      "PEOPLE",
      null, // data source id
      false, // separatedTransaction
      true // interruptExecution
    );
  }
  else {
    // update record
    utils.updateObject(
      obj,
      "PEOPLE",
      null, // data source id
      false, // separatedTransaction
      true // interruptExecution
    );
  }
}

The callback function for the second example (text file) would be:

var myCallbackFunction = function(line) { 
  // line is a javascript String containing the whole line just read
  var personCode = line.substring(0,10);
  var firstName = line.substring(10,30);
  var lastName = line.substring(30);

  var json = utils.executeQuery(
    "SELECT PERSON_CODE FROM PEOPLE WHERE PERSON_CODE=? ",
    null, // data source id
    false, // separatedTransaction
    true, // interruptExecution
    [personCode]
  );
  var list = JSON.parse(json); // here list is a zero length list in case the specified personCode does not exist in the db

  var obj = {
    personCode: personCode,
    firstName: firstName,
    lastName: lastName,
    enabled: "Y",
    createDate: utils.getCurrentDateAndTime()
  };

  var dataModelId = ... // data model id related to the table PEOPLE

  if (list.length==0) {
    // record does not exist yet: insert it
    utils.insertObject(
      obj,
      "PEOPLE",
      null, // data source id
      false, // separatedTransaction
      true // interruptExecution
    );
  }
  else {
    // update record
    utils.updateObject(
      obj,
      "PEOPLE",
      null, // data source id
      false, // separatedTransaction
      true // interruptExecution
    );
  }
}

In a more complex scenario, input data can be so large that an approach like the one reported above would be fairly heavy for the database, since a writing operation is always performed, for each input file, even when there is no line to update.

Let's take the scenario where there is 1 million lines in input with 1% of INSERTs (10.000 new records in the database) and only 10% of input lines to update (100.000 records), since all the others have not really changed. There would be 890.000 useless UPDATE operations carried out!

A way to avoid such a large useless updates is by adding in the table an additional text field (e.g. 255 length) containing an MD5 signature representing the whole line/record content. It would be possible to check it with the corresponding input line and avoid the update operation when the MD5 for the input line is the same as the MD5 for the already saved record in the table.

Example: suppose you have an MD5 text field in the table and a CSV input file with the same 3 fields as above:

var myCallbackFunction = function(obj) { 
  // obj is a javascript object containing a line read from the CSV file, having the structure:
  // { personCode: "..", firstName: "...", lastName: "..." }

  var inputMd5 = utils.md5(obj.personCode+"_"+obj.firstName+"_"+obj.lastName);

  var json = utils.executeQuery(
    "SELECT MD5 FROM PEOPLE WHERE PERSON_CODE=? ",
    null,
    false,
    true,
    [obj.personCode]
  );
  var list = JSON.parse(json); // here list is a zero length list in case the specified personCode does not exist in the db

  if (list.length==0) {
    // record does not exist yet: insert it
    utils.executeSql(
      "INSERT INTO PEOPLE(PERSON_CODE,FIRSTNAME,LASTNAME,MD5) VALUES(?,?,?,?) ",
      null, 
      false, 
      true,
      [ obj.personCode, obj.firstName, obj.lastName, inputMD5 ]
    );
  }
  else if (list[0].md5==null || list[0].md5!=inputMD5) {
    // update record
    utils.executeSql(
      "update PEOPLE set FIRSTNAME=?,LASTNAME=?,MD5=? WHERE PERSON_CODE=? ",
      null, 
      false, 
      true,
      [ obj.firstName, obj.lastName, inputMD5, obj.personCode ]
    );
  }
  else {
    // do nothing, since the MD5 is the same: no data changed!
  }
}

var attributeNames = ["personCode","firstName","lastName"]; 
var directoryId = ... // id for a directory defined in the AppDesigner
var fileName = "..."; // file name for the CSV file saved in the path specified by directory id

utils.readCSVFile(
  fileName,
  directoryId,
  ",", // fields separator: , or ;
  false, // flag used to skip the first line in the CSV file
  "myCallbackFunction",
  attributeNames
);

Optimizing csv reading and data loading on a single table

The best approach to read a csv file and save its content in a single table, is using the ad hoc method provided by Platform.

Example:

 var fileName = "..."; // file name
 var dirId = ...; // directory id where the file is located
 var tableName = "..."; // table where saving the csv content
 var defaultFieldNames = {
    CREATE_USER: userInfo.username,
    CREATE_DATE: utils.getCurrentDateAndTime()
 };
 var csvFields = [
   { fieldName: "personCode" },
   { fieldName: "firstName" },
   { fieldName: "lastName" },
   { fieldName: "birthDate", convertToSqlDate: "yyyy-MM-dd" }, 
   { fieldName: "lastPurchaseTime", convertToSqlTimestamp: "yyyy-MM-dd HH:mm:ss"},
   { fieldName: "id", progressive: "INTERNAL_UUID/INTERNAL_P"} 
 ];

 var processedRows = utils.readCSVFileAndWriteToTable( 
  fileName,
  directoryId,
  ";", // separator: , or ;
  false, // skip first row in the csv file
  null, // datastore Id
  tableName,
  defaultFieldNames,
  csvFields
 );
PreviousHow to filter a grid by date intervalNextHow to write text or csv files

Last updated 1 year ago

Was this helpful?