Aoife Lucas
Giga Expert

Sure, it can do this very easily.  I do it from an Inbound Action (email attachment). 

Do an manual import of the Excel first to let ServiceNow create the temp import table for you (don't really have to but it saves time).

Create transform map to translate the temp table into your production table.

Here's my script that uses the above items to import and run the transform:

(function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event, /*EmailWrapper*/ email, /*ScopedEmailLogger*/ logger, /*EmailClassifier*/ classifier) {
     
      var importSetTableName = "{your temp import table name}";
      var transformMapIDs = "{UUIDs of transform maps}";   //Use a comma to specify multiple transform maps
      var applicatonScope = "Global";
     
      // Create the datasource record
      current.name = "File import from: " + email.from;   //Feel free to rename this as appropriate
      current.import_set_table_name = importSetTableName;
      current.file_retrieval_method = "Attachment";
      current.type = "File";
      //current.format = "Excel"; // For Excel Files
      current.format = "CSV"; // For CSV Files
      current.header_row = 1;
      current.sheet_number = 1;
      current.sys_package.setDisplayValue(applicatonScope);
      current.sys_scope.setDisplayValue(applicatonScope);
      var dataSourceID = current.insert();

      /*
        * Schedule Load of Attachment
        *
        * This inbound email action will generate an import data source, however the attachment isn't copied to the data source until
        * after the insert of the record.   Scheduling the import to happen 30 seconds later so that attachment has time to be copied.
        */
      new global.EmailFileImportUtils().scheduleImport(dataSourceID, transformMapIDs);
     
})(current, event, email, logger, classifier);

Create a script include called EmailFileImportUtils:

var EmailFileImportUtils = Class.create();
EmailFileImportUtils.prototype = {
	initialize: function() {
	},
	
	scheduleImport: function(dataSourceID, transformMapIDs) {
		/*
 		* Create scheduled job to process import
 		*
 		* The inbound email action will generate an import data source, however the attachment isn't copied to the data source until
 		* after the insert of the record.   The code below will create a scheduled job to process the import 30 seconds later
 		* so that attachment has time to be copied to the data source from the email.
 		*/
		
		var schRec = new GlideRecord("sys_trigger");
		schRec.name = "Load Data Source: " + dataSourceID;
		schRec.trigger_type = 0;   // Run Once
		schRec.script = "new global.EmailFileImportUtils().loadImportSet('" + dataSourceID + "', '" + transformMapIDs + "')";
		
		var nextAction = new GlideDateTime();
		nextAction.addSeconds(30);   // 30 seconds should be enough time however this can be changed.
		schRec.next_action = nextAction;
		schRec.insert();
	},
	
	loadImportSet: function(dataSourceID, transformMapIDs) {
		// Get Datasource Record
		var dataSource = new GlideRecord("sys_data_source");
		dataSource.get(dataSourceID);
		
		// If CSV and header isn't on row 1, recreate attachment with empty rows removed
		if (dataSource.getValue("format") == "CSV" && dataSource.getValue("header_row") > 1) {
			var attachmentRec = new GlideRecord("sys_attachment");
			attachmentRec.addQuery("table_sys_id", dataSource.getValue("sys_id"));
			attachmentRec.query();
			if (attachmentRec.next()) {
				var oldAttachmentID = attachmentRec.getValue("sys_id");
				var inputStream = new GlideSysAttachment().getContentStream(oldAttachmentID);
				var textReader = new GlideTextReader(inputStream);
				var ln = " ";
				var newLine = "";
				
				var lineCounter = 0;
				var headerRow = parseInt(dataSource.getValue("header_row"));
				while((ln = textReader.readLine()) != null) {
					lineCounter += 1;
					if (lineCounter < headerRow) {
						continue;
					}
					
					if (ln.length > 1) {
						newLine += ln + "\n";
					}
				}
				new GlideSysAttachment().write(dataSource, 'Changed ' + attachmentRec.getValue('file_name'), "text/csv", newLine);
			}
		}		
		
		// Process data source file
		var loader = new GlideImportSetLoader();
		var importSetRec = loader.getImportSetGr(dataSource);
		var ranload = loader.loadImportSetTable(importSetRec, dataSource);
		importSetRec.state = "loaded";
		importSetRec.update();
		
		// Transform import set
		var transformWorker = new GlideImportSetTransformerWorker(importSetRec.sys_id, transformMapIDs);
		transformWorker.setBackground(true);
		transformWorker.start();
	},
	
	type: 'EmailFileImportUtils'
	
};

Works like a champ.  Thought I had a comment on that script include to give credit to the original author.  I cannot recall who it was but would like to add that into my script include to get proper attribution.  This script is a life saver.

Tapadh leat,

Aoife