define([
|
'exports',
|
'dojo/_base/lang',
|
'dojo/_base/array',
|
'dojo/_base/html',
|
'dojo/has',
|
'dojo/Deferred',
|
'jimu/utils',
|
'esri/lang',
|
'esri/tasks/QueryTask',
|
'esri/tasks/query',
|
'esri/graphic',
|
"jimu/ArcadeUtils"],
|
function(exports, lang, array, html, has, Deferred, jimuUtils, esriLang, QueryTask, Query,
|
Graphic, ArcadeUtils) {
|
/*
|
** filename String no file extension
|
** datas Object[]
|
** columns Object[]
|
*/
|
exports.exportCSV = function(filename, datas, columns) {
|
return exports._createCSVStr(datas, columns).then(function(content) {
|
return exports._download(filename + '.csv', content);
|
});
|
};
|
|
/*
|
** filename String no file extension
|
** layer FeatureLayer or LayerDefinition Object; if is FeatureLayer, layer.loaded must be true
|
** options Object
|
** options: {
|
** datas: Array of feature.attributes; if not null only exported this datas to CSV
|
** fromClient: if true get data from layer.graphics,
|
** if false get first `layer.maxRecordCount` data from server
|
** outFields: Array of Field; if null export all fields of layer
|
** filterExpression: set where clause from featureService
|
** formatNumber: Boolean. if true localize number type field
|
** formatDate: Boolean. if true localize date type field
|
** formatCodedValue: Boolean. if true use description instead of codedvalue
|
** popupInfo: https://developers.arcgis.com/javascript/jshelp/intro_popuptemplate.html
|
** }
|
*/
|
exports.exportCSVFromFeatureLayer = function(filename, layer, options) {
|
options = options || {};
|
var exportOptions = {
|
datas: options.datas,
|
objectIds: options.objectIds,
|
fromClient: options.fromClient,
|
withGeometry: options.withGeometry,
|
outFields: options.outFields,
|
filterExpression : options.filterExpression,
|
outSpatialReference: options.outSpatialReference,
|
arcadeExpressions: options.arcadeExpressions
|
};
|
return exports._getExportData(layer, exportOptions).then(function(result) {
|
var formattedOptions = {
|
formatNumber: options.formatNumber,
|
formatDate: options.formatDate,
|
formatCodedValue: options.formatCodedValue,
|
richText: {
|
clearFormat: options.richTextFieldsToClear && !!options.richTextFieldsToClear.length,
|
fieldsToClear: options.richTextFieldsToClear || []
|
},
|
popupInfo: options.popupInfo
|
};
|
return exports._formattedData(layer, result, formattedOptions)
|
.then(function(formattedResult) {
|
return exports.exportCSV(filename, formattedResult.datas, formattedResult.columns);
|
});
|
});
|
};
|
|
/*
|
** filename String no file extension
|
** definition LayerDefinition Object
|
** attributes Array of graphic.attributes
|
** options: {
|
** datas: Array of feature.attributes; if not null only exported this datas to CSV
|
** fromClient: if true get data from layer.graphics,
|
** if false get first `layer.maxRecordCount` data from server
|
** outFields: Array of Field; if null export all fields of layer
|
** filterExpression: set where clause from featureService
|
** formatNumber: Boolean. if true localize number type field
|
** formatDate: Boolean. if true localize date type field
|
** formatCodedValue: Boolean. if true use description instead of codedvalue
|
** popupInfo: https://developers.arcgis.com/javascript/jshelp/intro_popuptemplate.html
|
** }
|
*/
|
exports.exportCSVByAttributes = function(filename, definition, attributes, options) {
|
options = lang.mixin({}, options);
|
options.datas = attributes;
|
return exports.exportCSVFromFeatureLayer(filename, definition, options);
|
};
|
|
/*
|
** filename String no file extension
|
** definition LayerDefinition Object
|
** graphics Array of graphic
|
** options: {
|
** datas: Array of feature.attributes; if not null only exported this datas to CSV
|
** fromClient: if true get data from layer.graphics,
|
** if false get first `layer.maxRecordCount` data from server
|
** outFields: Array of Field; if null export all fields of layer
|
** filterExpression: set where clause from featureService
|
** formatNumber: Boolean. if true localize number type field
|
** formatDate: Boolean. if true localize date type field
|
** formatCodedValue: Boolean. if true use description instead of codedvalue
|
** popupInfo: https://developers.arcgis.com/javascript/jshelp/intro_popuptemplate.html
|
** }
|
*/
|
exports.exportCSVByGraphics = function(filename, definition, graphics, options) {
|
var attributes = array.map(graphics, function(graphic) {
|
return graphic.attributes;
|
});
|
return exports.exportCSVByAttributes(filename, definition, attributes, options);
|
};
|
|
exports._createCSVStr = function(datas, columns) {
|
var def = new Deferred();
|
var textField = '"';
|
var content = "";
|
var len = 0,
|
n = 0,
|
comma = "",
|
value = "";
|
try {
|
columns = array.map(columns, function(f){
|
if(typeof f === 'string'){
|
return {name: f};
|
}else{
|
return f;
|
}
|
});
|
array.forEach(columns, function(_field) {
|
var _fieldText = _field.alias || _field.name;
|
// append "" to fields that include commas
|
if(_fieldText.toString().indexOf(",") > -1) {
|
_fieldText = '"' + _fieldText + '"';
|
}
|
content = content + comma + _fieldText;
|
comma = ",";
|
});
|
|
content = content + "\r\n";
|
len = datas.length;
|
n = columns.length;
|
for (var i = 0; i < len; i++) {
|
comma = "";
|
for (var m = 0; m < n; m++) {
|
var _field = columns[m];
|
value = datas[i][_field.name];
|
if (!value && typeof value !== "number") {
|
value = "";
|
}
|
if (value && /[",\r\n]/g.test(value)) {
|
value = textField + value.replace(/(")/g, '""') + textField;
|
}
|
content = content + comma + value;
|
comma = ",";
|
}
|
content = content + "\r\n";
|
}
|
def.resolve(content);
|
} catch (err) {
|
console.error(err);
|
def.resolve("");
|
}
|
|
return def;
|
};
|
|
exports._isIE11 = function() {
|
return jimuUtils.has('ie') === 11;
|
};
|
|
exports._isEdge = function() {
|
return jimuUtils.has('edge');
|
};
|
|
exports._getDownloadUrl = function(text) {
|
var BOM = "\uFEFF";
|
// Add BOM to text for open in excel correctly
|
if (window.Blob && window.URL && window.URL.createObjectURL) {
|
var csvData = new Blob([BOM + text], { type: 'text/csv' });
|
return URL.createObjectURL(csvData);
|
} else {
|
return 'data:attachment/csv;charset=utf-8,' + BOM + encodeURIComponent(text);
|
}
|
};
|
|
exports._download = function(filename, text) {
|
var def = new Deferred();
|
try {
|
if (has('ie') && has('ie') < 10) {
|
// has module unable identify ie11 and Edge
|
var oWin = window.top.open("about:blank", "_blank");
|
oWin.document.write('sep=,\r\n' + text);
|
oWin.document.close();
|
oWin.document.execCommand('SaveAs', true, filename);
|
oWin.close();
|
}else if (has("ie") === 10 || exports._isIE11() || exports._isEdge()) {
|
var BOM = "\uFEFF";
|
var csvData = new Blob([BOM + text], { type: 'text/csv' });
|
navigator.msSaveBlob(csvData, filename);
|
} else {
|
var link = html.create("a", {
|
href: exports._getDownloadUrl(text),
|
target: '_blank',
|
download: filename
|
}, document.body);
|
if (has('safari')) {
|
// # First create an event
|
var click_ev = document.createEvent("MouseEvents");
|
// # initialize the event
|
click_ev.initEvent("click", true /* bubble */ , true /* cancelable */ );
|
// # trigger the evevnt/
|
link.dispatchEvent(click_ev);
|
} else {
|
link.click();
|
}
|
|
html.destroy(link);
|
}
|
def.resolve();
|
} catch(e) {
|
def.reject(e);
|
}
|
return def;
|
};
|
|
exports._getExportData = function(layer, options) {
|
var def = new Deferred();
|
var _outFields = null;
|
var _queryOutFields = [];
|
var data = options.datas;
|
var withGeometry = options.withGeometry;
|
var withExpressionFields = !!options.arcadeExpressions;
|
|
_outFields = options.outFields;
|
if (!_outFields || !_outFields.length) {
|
_outFields = layer.fields;
|
}
|
_outFields = lang.clone(_outFields);
|
|
if (withGeometry && !(data && data.length > 0)) {// only for fromClient or server
|
// data is null, we should retrieve data from server.
|
// for query params, here we clone _outFields to _queryOutFields before x and y appended to _outFields,
|
// or we clone all fields from layer object, if it contains arcade expressions.
|
// because the fields of service might not contain field x or field y.
|
if(withExpressionFields) {
|
var _outFieldsWithoutExprs = array.filter(layer.fields, function(field) {
|
return field.name.indexOf('expression/') === -1;
|
});
|
_queryOutFields = lang.clone(_outFieldsWithoutExprs);
|
} else {
|
_queryOutFields = lang.clone(_outFields);
|
}
|
|
var name = "";
|
if (_outFields.indexOf('x') !== -1) {
|
name = '_x';
|
} else {
|
name = 'x';
|
}
|
_outFields.push({
|
'name': name,
|
alias: name,
|
format: {
|
'digitSeparator': false,
|
'places': 6
|
},
|
show: true,
|
type: "esriFieldTypeDouble"
|
});
|
if (_outFields.indexOf('y') !== -1) {
|
name = '_y';
|
} else {
|
name = 'y';
|
}
|
_outFields.push({
|
'name': name,
|
alias: name,
|
format: {
|
'digitSeparator': false,
|
'places': 6
|
},
|
show: true,
|
type: "esriFieldTypeDouble"
|
});
|
}
|
|
if (data && data.length > 0) {
|
if(withExpressionFields) {
|
data = exports._getAttrsWithExpressionsBatch(data, options.arcadeExpressions);
|
}
|
def.resolve({
|
'data': data || [],
|
'outFields': _outFields
|
});
|
} else {
|
// var g = null;
|
if (options.fromClient) {
|
data = array.map(layer.graphics, function(graphic) {
|
var attrs = withGeometry ? getAttrsWithXY(graphic) : lang.clone(graphic);
|
attrs = withExpressionFields ?
|
exports._getAttrsWithExpressions(attrs, options.arcadeExpressions) : attrs;
|
return attrs;
|
});
|
def.resolve({
|
'data': data || [],
|
'outFields': _outFields
|
});
|
} else {
|
exports._getExportDataFromServer(layer, _queryOutFields, options)
|
.then(function(data) {
|
if(withExpressionFields) {
|
data = exports._getAttrsWithExpressionsBatch(data, options.arcadeExpressions);
|
}
|
def.resolve({
|
'data': data || [],
|
'outFields': _outFields
|
});
|
});
|
}
|
}
|
|
return def;
|
};
|
|
exports._getExportDataFromServer = function(layer, outFields, options) {
|
var def = new Deferred();
|
if (layer.declaredClass !== 'esri.layers.FeatureLayer') {
|
def.resolve([]);
|
return def;
|
}
|
var qt = new QueryTask(layer.url);
|
var query = new Query();
|
query.where = options.filterExpression ||
|
(layer.getDefinitionExpression && layer.getDefinitionExpression()) || "1=1";
|
var oFields = outFields;
|
if (oFields.length > 0) {
|
var oNames = array.map(oFields, function(field) {
|
return field.name;
|
});
|
query.outFields = oNames;
|
} else {
|
query.outFields = ["*"];
|
}
|
query.objectIds = options.objectIds;
|
query.returnGeometry = options.withGeometry;
|
query.outSR = options.spatialReference;
|
|
qt.execute(query, function(results) {
|
var data = array.map(results.features, function(feature) {
|
return getAttrsWithXY(feature);
|
});
|
def.resolve(data);
|
}, function(err) {
|
console.error(err);
|
def.resolve([]);
|
});
|
|
return def;
|
};
|
|
exports._formattedData = function(layer, dataOptions, formattedOptions) {
|
var def = new Deferred();
|
var formattedDatas = [];
|
|
var datas = dataOptions.data;
|
var outFields = dataOptions.outFields;
|
|
for (var i = 0, len = datas.length; i < len; i++) {
|
var aliasData = {};
|
for (var j = 0; j < outFields.length; j++) {
|
var _field = outFields[j];
|
aliasData[_field.name] = exports._getExportValue(
|
datas[i][_field.name],
|
_field,
|
layer.objectIdField,
|
layer.typeIdField,
|
datas[i][layer.typeIdField],
|
layer.types,
|
formattedOptions
|
);
|
}
|
formattedDatas.push(aliasData);
|
}
|
|
var columns = array.map(outFields, function(oField) {
|
return {
|
alias: oField.alias,
|
name: oField.name
|
}
|
});
|
|
def.resolve({
|
datas: formattedDatas,
|
columns: columns
|
});
|
return def;
|
};
|
|
exports._getExportValue = function(data, field, pk, typeIdField,
|
typeData, types, formattedOptions) {
|
var pInfos = formattedOptions.popupInfo;
|
function getFormatInfo(fieldName) {
|
if (pInfos && esriLang.isDefined(pInfos.fieldInfos)) {
|
for (var i = 0, len = pInfos.fieldInfos.length; i < len; i++) {
|
var f = pInfos.fieldInfos[i];
|
if (f.fieldName === fieldName) {
|
return f.format;
|
}
|
}
|
}
|
|
return null;
|
}
|
var fieldsToClear = formattedOptions.richText.fieldsToClear;
|
function isRichTextField(fieldName) {
|
for (var i = 0, len = fieldsToClear.length; i < len; i++) {
|
var f = fieldsToClear[i];
|
if (f.fieldName === fieldName) {
|
return true;
|
}
|
}
|
return false;
|
}
|
var isDomain = !!field.domain && formattedOptions.formatCodedValue;
|
var isDate = field.type === "esriFieldTypeDate" && formattedOptions.formatDate;
|
var isOjbectIdField = pk && (field.name === pk);
|
var isTypeIdField = typeIdField && (field.name === typeIdField);
|
var isRichTextField = field.type === "esriFieldTypeString" &&
|
formattedOptions.richText.clearFormat &&
|
isRichTextField(field.name);
|
|
if (isDate) {
|
return jimuUtils.fieldFormatter.getFormattedDate(data, getFormatInfo(field.name));
|
}
|
if (isTypeIdField) {
|
return jimuUtils.fieldFormatter.getTypeName(data, types);
|
}
|
if (isDomain) {
|
return jimuUtils.fieldFormatter.getCodedValue(field.domain, data);
|
}
|
if (isRichTextField) {
|
if(data) {
|
var d = document.createElement('span');
|
d.innerHTML = data;
|
return d.textContent || d.innerText || '';
|
} else {
|
return data;
|
}
|
}
|
if (!isDomain && !isDate && !isOjbectIdField && !isTypeIdField && !isRichTextField) {
|
var codeValue = null;
|
if (pk && types && types.length > 0) {
|
var typeChecks = array.filter(types, function(item) {
|
// value of typeIdField has been changed above
|
return item.id === typeData;
|
});
|
var typeCheck = typeChecks && typeChecks[0];
|
|
if (typeCheck && typeCheck.domains &&
|
typeCheck.domains[field.name] && typeCheck.domains[field.name].codedValues) {
|
codeValue = jimuUtils.fieldFormatter.getCodedValue(
|
typeCheck.domains[field.name],
|
data
|
);
|
}
|
}
|
return codeValue !== null ? codeValue : data;
|
}
|
|
return data;
|
};
|
|
exports._getAttrsWithExpressions = function(attributes, arcadeExpressions) {
|
var expressionInfos = lang.getObject('expressionInfos', false, arcadeExpressions),
|
layerDefinition = lang.getObject('layerDefinition', false, arcadeExpressions),
|
graphic = new Graphic(null, null, attributes);
|
return ArcadeUtils.customExpr.getAttributesFromCustomArcadeExpr(
|
expressionInfos, graphic, layerDefinition) || attributes;
|
};
|
|
exports._getAttrsWithExpressionsBatch = function(odata, arcadeExpressions) {
|
var data = [];
|
data = array.map(odata, function(attrs) {
|
return exports._getAttrsWithExpressions(attrs, arcadeExpressions);
|
});
|
return data;
|
};
|
|
function getAttrsWithXY(graphic) {
|
var attrs = lang.clone(graphic.attributes);
|
var geometry = graphic.geometry;
|
if (geometry && geometry.type === 'point') {
|
if ('x' in attrs) {
|
attrs._x = geometry.x;
|
} else {
|
attrs.x = geometry.x;
|
}
|
|
if ('y' in attrs) {
|
attrs._y = geometry.y;
|
} else {
|
attrs.y = geometry.y;
|
}
|
}
|
|
return attrs;
|
}
|
|
});
|