我想根据用户提供的行数和列数来过滤数据。
我从给定位置读取excel文件后获取控制器上的数据,并且excel可能包含多个工作表。工作表名称将显示在下拉列表中。
我想根据通过列的标题名称过滤行数据,以便该行只有值,直到定义列。目前我正在获得整行值。
我写过这样的逻辑,但这不起作用。
var rowData=[];
for(var i=0;i<headerNames.length;i++){//headerNames contains column names
for(var j=0;j<data.length;j++){//data contains the rows data
for(var keyName in data[j])
if(angular.equals(keyName,headerNames[i])){
rowData.push({'keyName':data[j][keyName]})//I want only the key,values which matches the column names. I want to set the keyName value as array key but I am not getting its value instead it is coming like keyName:18
}
}
}
}
为代码添加plunker。 http://plnkr.co/edit/28Z44xDBug7nFCQnKZJL?p=preview
我能够在UI上过滤数据,并根据用户输入仅获取行和列数据。 但我需要控制器上的相同数据,以便我可以将其保存在MongoDb中。我想根据列输入过滤行数据。所以,我只得到行数据,直到列定义。
请建议我如何过滤数据并且可以拼接行值,以便在行i中可以具有最多定义的列数的值。例如,如果用户输入了4行和5列,那么在我的行Data中,我只能拥有最多5列的值以及我可以从数组中删除的所有其他值。在我的代码中,我目前无法将键值设置为数组键。
请帮我解决此问题。
答案 0 :(得分:0)
您应该尝试在内循环中更改为:
var obj = {};
obj[keyName] = data[j][keyName];
rowData.push(obj);
注意:我还对工作表选择进行了一些改进,现在它在您上传新文件时默认为第一张工作表。 我也认为你的重置有问题,它在重置后不接受新的工作簿,它只使用前一个。
// Code goes here
angular.module('app', ['ui.grid'])
.controller('MainCtrl', ['$scope', function ($scope) {
var vm = this;
vm.gridOptions = {};
vm.reset = reset;
vm.selectedSheet = '';
vm.sheetIndex = 0;
function reset() {
vm.gridOptions.data = [];
vm.gridOptions.columnDefs = [];
vm.selectedSheet = '';
vm.sheetIndex = 0;
vm.sheetNames = [];
vm.updatedData = null;
}
vm.readSheet = function () {
var workbook = XLSX.read(vm.data, {
type: 'binary'
});
var headerNames = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[vm.sheetIndex]], {
header: 1
})[0];
vm.sheetNames = workbook.SheetNames; //Passed the sheet names to scope variable
if(!vm.selectedSheet && vm.sheetNames && vm.sheetNames.length > 0) {
vm.selectedSheet = vm.sheetNames[0];
}
var data = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[vm.sheetIndex]]);
var row = $scope.rowCount;
var col = $scope.columnCount;
if (col != undefined && col != '') {
headerNames.splice($scope.columnCount);
}
vm.gridOptions.columnDefs = [];
headerNames.forEach(function (h) {
vm.gridOptions.columnDefs.push({
field: h
});
});
if (row != undefined && row != '') {
data.splice($scope.rowCount);
}
vm.gridOptions.data = data;
var rowData = [];
for (var i = 0; i < headerNames.length; i++) {
for (var j = 0; j < data.length; j++) {
for (var keyName in data[j]) {
if (angular.equals(keyName, headerNames[i])) {
var obj = {};
obj[keyName] = data[j][keyName];
rowData.push(obj);//Here I am trying to create
//an similar data kind array which will have only the row values upto
//the column defined. But in keyName I am not getting the key value
//Also please suggest is this the right approach. I need only the data
//here upto the row and column defined by user so that I can save that data
//to mongoDB
}
}
}
}
vm.updatedData = rowData;
};
vm.onLoadData = function (data) {
vm.data = vm.data || data;
vm.readSheet();
};
vm.sheetChange = function () {
vm.sheetIndex = vm.sheetNames.indexOf(vm.selectedSheet);
vm.readSheet();
};
$scope.$watch('columnCount', function(newVal, oldVal) {
if(newVal !== oldVal) {
vm.readSheet();
}
});
$scope.$watch('rowCount', function(newVal, oldVal) {
if(newVal !== oldVal) {
vm.readSheet();
}
});
}])
.directive("fileread", [function () {
return {
scope: {
onLoadData: '&'
},
link: function ($scope, $elm, $attrs) {
$elm.on('change', function (changeEvent) {
var reader = new FileReader();
reader.onload = function (evt) {
$scope.$apply(function () {
$scope.onLoadData({
data: evt.target.result
});
$elm.val(null);
});
};
reader.readAsBinaryString(changeEvent.target.files[0]);
});
}
}
}]);
/* Styles go here */
body {
/* font-family: Verdana; */
padding: 20px;
}
.grid {
width: 100%;
height: 250px;
}
.grid-msg-overlay {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
background: rgba(0, 0, 0, 0.4);
}
.grid-msg-overlay .msg {
opacity: 1;
position: absolute;
top: 20%;
left: 20%;
width: 60%;
height: 50%;
background-color: #eee;
border-radius: 4px;
border: 1px solid #555;
text-align: center;
font-size: 24px;
display: table;
}
.grid-msg-overlay .msg > .center {
display: table-cell;
vertical-align: middle;
}
.grid input[type="file"] {
font-size: 14px;
display: inline-block;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<link data-require="bootstrap-css@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.js"></script>
<script src="https://cdn.rawgit.com/SheetJS/js-xlsx/v0.8.0/dist/xlsx.full.min.js"></script>
<script src="https://cdn.rawgit.com/SheetJS/js-xlsx/v0.8.0/dist/ods.js"></script>
<script src="http://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/release/3.0.0-rc.22/ui-grid.min.js"></script>
<link rel="stylesheet" href="http://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/release/3.0.0-rc.22/ui-grid.min.css" />
<link rel="stylesheet" href="main.css" type="text/css" />
</head>
<body>
<div ng-controller="MainCtrl as vm">
<button type="button" class="btn btn-success" ng-click="vm.reset()">Reset Grid</button>
<br />
<br />
<div id="grid1" ui-grid="vm.gridOptions" class="grid">
<div class="grid-msg-overlay" ng-show="!vm.gridOptions.data.length">
<div class="msg">
<div class="center">
<span class="muted">Select Spreadsheet File</span>
<br />
<input type="file" accept=".xls,.xlsx,.ods" multiple="true" fileread="" on-load-data="vm.onLoadData(data)"/>
</div>
</div>
</div>
</div>
<div ng-show="vm.sheetNames && vm.sheetNames.length > 0">
<br/>
<div ng-show="vm.sheetNames.length > 1">
<select ng-model="vm.selectedSheet" ng-options="names as names for names in vm.sheetNames"
ng-change="vm.sheetChange()"></select>
</div>
<br/>
<label>Column:
<input type="text" name="col" ng-model="columnCount">
</label>
<br/>
<label>Row:
<input type="text" name="row" ng-model="rowCount">
</label>
<br/><br/>
<div ng-show="vm.updatedData">
<label>Updated result:</label>
<div>{{vm.updatedData}}</div>
</div>
</div>
</div>
<script src="app.js"></script>
</body>
</html>