Search the fields in Database - database

What is the best way for searching the fields AT THE MOMENT in database with angularjs?
I have a JSON inside a field of database...
I want, when a user fill a text box (TextBox1), in exact time, it search at the moment inside my database. if that entire text was equal with any field of a table, fill another textbox(TextBox2) automatically.
With below code, i can fill it. and it works properly. but i thinks its not logical. Because it reads all of my data in mentioned Table first
$scope.showFullName = function(){
$scope.Fullname="";
if($scope.MembersNationalCode.length == 10) {
for (var i = 0; i < $scope.NaturalMembers.length; i++) {
if ($scope.NaturalMembers[i].NationalNumber == $scope.MembersNationalCode) {
$scope.Fullname = $scope.NaturalMembers[i].Name + " " + $scope.NaturalMembers[i].Family;
}
}
}
};
I'm mentioning again. It works properly. But i'm looking for best way. And this question is a sample.
Thanks.

Related

Merging 2 or more JSON datasets by aligning the values based on the same value in Google Scripts [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 10 months ago.
Improve this question
I have several datasets based in JSON. This is because the datasets are pulled in through an API call. I can change this, if it makes sense, but it might slow down the intended function a lot.
Now, each dataset could easily 10,000 and even 100,000 records within i.e. dataset.length = 10,000.
Now in each of these datasets, they have an id column that allows me to connect them. I essentially want to select a primary dataset, and then cycle through the secondary datasets, find the first record (or even all records) where that share the same identifier. let's say primary.id = secondary.id
This is essentially like an INNER JOIN but running through with JSON and using Google Scripts.
I want to match the rows in the secondary datasets and just add them to the relevant places in the primary and output just one dataset to the file.
I wrote the following script
function mergeRecords(primary,identifiers,columns) {
const args = Array.prototype.slice.call(arguments);
args.splice(0,3);
const argsFlat = args.flat();
if (args.length<1) {
throw 'Insufficient Number of datasets, please add at least 1 secondary dataset';
}
try {
for (var i in primary) {
var parent = primary[i];
var a = 0;
var child = argsFlat[a];
while (parent[identifiers] != child[identifiers] && a<argsFlat.length) {
a++;
}
columns.forEach(function(x) {
parent['Child-'+x]=child[x];
}
);
}
return primary;
} catch(err) {
Logger.log(err);
Logger.log(primary);
Logger.log(arguments);
Logger.log(argsFlat);
Logger.log(columns);
Logger.log(identifiers);
Logger.log(a);
Logger.log(parent.id+' '+child.id);
}
}
Essentially the primary is the main dataset to compare all the others against. The identifier is the name of the key that should be the same in target secondary datasets. columns are the data properties I want to retrieve from the secondary sets.
As you can see, I've made it that arguments need to be included after the columns argument otherwise it errors out.
I am using the while method/function (honestly I'm not sure the difference, I'm still new to this) because I have found it to be quite a bit faster than using
for (var a in argsFlat) {
var child = argsFlat[a];
if (parent[identifiers] == child[identifiers]) {
columns.forEach(function(x) {
parent['Child-'+x]=child[x];
}
);
else {continue;}
even though using this would allow to append the data from the different datasets if multiple datasets have the same identifier as the parent.
This is the test source I am using:
function test() {
var primary = {
'records': [{
'id':1234445,
'name':'Yiz Segall1',
'email':'123#123.com'},
{
'id':567568,
'name':'viva1',
'email':'old#new.com1'
},
{
'id':123442,
'name':'shompie1',
'email':'shompie#gmail.com1'
}]
}
var secondary = {
'records': [{
'id':1234445,
'name':'2Yiz Segall',
'email':'2123#123.com',
'phone':12435435},
{
'id':567568,
'name':'2viva',
'email':'2old#new.com',
'phone':4445555
},
{
'id':123442,
'name':'2shompie',
'email':'2shompie#gmail.com',
'phone':5556666
}]
}
var tertiary = {
'records': [{
'id':1234445,
'name':'3Yiz Segall',
'email':'3123#123.com',
'address':'32 wisconsin avenue'
},
{
'id':567568,
'name':'3viva',
'email':'o3ld#new.com',
'address':'14 pine street'
},
{
'id':123442,
'name':'s3hompie',
'email':'3shompie#gmail.com',
'address':'15 ny street'
}]
}
var records = mergeRecords(primary.records,'id',['name','email'],secondary.records,tertiary.records);
Logger.log(records);
}
My question is 2-fold:
While the first record in the test comes back correct, the others just pull in the first data, so how do I fix?
this is the response I get from the test [{email=123#123.com, Child-name=2Yiz Segall, name=Yiz Segall1, Child-email=2123#123.com, id=1234445.0}, {email=old#new.com1, name=viva1, Child-name=2Yiz Segall, id=567568.0, Child-email=2123#123.com}, {name=shompie1, email=shompie#gmail.com1, Child-name=2Yiz Segall, Child-email=2123#123.com, id=123442.0}]
If I wanted to make it that it would attach all data rows that had the same identifier as the primary row, I have a problem with naming. Right now, it uses parent['Child-'+x]=child[x]; which only works for the first instance of this. How do I make it child1 and then child 2 and then child 3, so it's flexible enough to adapt to however many datasets I need to include.
I thought of using the dataset names, but the data is converted into an array and then flattened, so it's impossible to tell where it came from, or is there an eays way to do that?
Remember that this process plays a part of preparing the data properly to output into a file, by this point, I have already run script to make 3-4 API calls.
Any help is welcome, thanks.
As a guess. Try to change this:
parent['Child-'+x]=child[x];
With this:
if (!parent['Child-' + x]) {
parent['Child-' + x] = child[x];
} else {
let counter = 1;
while (parent['Child' + counter + '-' + x]) continue;
parent['Child' + counter + '-' + x] = child[x];
}

Slow Google Script - difficulties batching information into an array

I've been struggling with a little project of mine for a while now, and was looking for some assistance. The key issue I believe is simply me not being familiar with array script language and how to approach this. I've tried a few things after researching on here a bit and reading through the Best Practices section, but haven't been able to get it functioning adequately.
My script needs to be able to collect 200 rows x 200 columns of data from a spreadsheet, and depending on the number within each cell, it needs to select the corresponding number of columns next to that number and colour them in.
This was really simple to do with my basic programming knowledge, by just getting it to select each cell, check the number, select that range with an offset and then change the colour and move onto the next cell, however my code is incredibly slow because it does everything within the sheet without batching the data, and can't complete the full range within Google Script's time allowance. Any assistance on speeding it up would be greatly appreciated, as I haven't been able to get this working using arrays.
Here's the code I'm working with currently:
function CreateCalendar() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sheet=ss.getSheetByName('Sheet2');
var selection=ss.getRange("Sheet2!H2:FC140");
var columns=selection.getNumColumns();
var rows=selection.getNumRows();
for (var column=1; column < columns; column++) {
for (var row=1; row < rows; row++) {
var cell=selection.getCell(row,column);
var cellvalue=cell.getValue();
if (cellvalue >= 1) {
var range=cell.offset(0,0,1,cellvalue);
range.setBackground("blue");
}
else {;}
}
}
}
Here's a public spreadsheet with confidential info removed and the sheet I'm targeting is Sheet2. Any assistance I could get on this would be greatly appreciated! Thanks
https://docs.google.com/spreadsheets/d/1Oe0aacfSBMmHpZvGPmjay5Q1bqBebnGQV4xlsK8juxk/edit#gid=0
You need to get rid of the repeated calls to range.getValue(). You can get all of the values for the range in one call & then iterate over that array in-script.
For your script it would look something like this:
function CreateCalendar() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sheet=ss.getSheetByName('Sheet2');
var selection=ss.getRange("Sheet2!H1:FC140"); // <= include header, but we'll skip it when we get to stepping over the array
var values = selection.getValues(); // <= get all of the values now in one call
for (var r=1; r < values.length; r++) {
for (var c=0; c < values[r].length; c++) {
if (values[r][c] >= 1) {
var range=sheet.getRange(r+1, c+8, 1, values[r][c]); // r+1 & c+8 because of array offsets
range.setBackground("blue");
}
else {;}
}
}
}
Take a look at Google's documentation: range.GetValues() https://developers.google.com/apps-script/reference/spreadsheet/range#getValues()
How about following sample script? If this is not your expectation, I would like to modify this script.
Sample script :
function CreateCalendar() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sheet=ss.getSheetByName('Sheet2');
var data = sheet.getRange("H2:FC140").getValues();
data.forEach(function(e1, i1){
e1.forEach(function(e2, i2){
if (e2 >= 1) {
sheet.getRange(i1+2, i2+8).offset(0,0,1,e2).setBackground("blue");
}
})
})
}
Result (sample) :
If I misunderstand your question, I'm sorry.

angularjs correct row is not being deleted from table

I have been struggling with a couple of issue so I thought I would reach out for help after doing much searching. I'm using AngularJS.
My first problem is that checkbox is not working properly when I use ng-repeat, it will only check the first box in the table code snippet below. I'm using a custom checkbox which I coded with css is the reason for the label.
My second issue is when I click on the check box it should delete any row I want but it deletes the row before it if I start from the bottom of the table up, but if I start from the top of the table down it works as expected except for the box being checked code snippet. I tried many ways to set the index but it still does not work.
$scope.removeRow = function(type) {
var index = -1;
var myArr = eval( $scope.contacts );
for( var i = 0; i < myArr.length; i++ ) {
if( myArr[i].type === type ) {
index = i;
break;
}
{
if( index === -1 ) {
alert( "Something gone wrong" );
}
$scope.contacts.splice(index, 1);
};
First off, don't use eval($scope.contacts). If that variable is a string and contains javascript it will run that javascript. if myArr isn't defined using myArr = $scope.contacts you can use myArr = JSON.parse(JSON.stringify($scope.contacts) or use angular.copy method.
I don't see your html, so I can't tell you why your checkbox doesn't work. But regarding your second problem, if it's deleting a row above when you hit splice, why not change that code to :
$scope.contacts.splice(index + 1, 1)

Using AngularJS to validate dynamically created 'input' element

I have a table that displays several entries, each has an <input>. The user can dynamically add additional inputs by clicking an "add entry" button. I need to iterate over them before saving and validate each one. I simplified my example to check that the value of each input is greater than 100 (ultimately I will use a pattern-match to validate MAC and IP addresses).
I can probably handle it if I could select all <input>s, but I would really like to select a specific <input> using an index I already have in my scope. I read that angular.element is a way, but I need to select something that was dynamically created, and thus not named something easy like id="myInput". Unless I use an id of "input" and append a unique number with Angular's $index in the id attribute?
Here is my Fiddle that shows what I'm doing. Line 44 is an if() that should check if any <input> is greater than 100. The "Save Row" button validates that the input is greater than 100, but if you edit a line, I need the "Save" button to validate any that the user has edited (by clicking Edit next to it).
tl;dr:
How can I use Angular to select an <input> that has been created dynamically?
I have updated your fiddle in a clean way so that you can maintain the validation in a generic method for both add & edit.
function validateBinding(binding) {
// Have your pattern-match validation here to validate MAC and IP addresses
return binding.ip > 100;
}
Updated fiddle:
https://jsfiddle.net/balasuar/by0tg92m/27/
Also, I have fixed the current issue with editing you have to allow multiple editing without save the first row when clicking the next edit on next row.
The validation of 'save everything' is now cleaner in angular way as below.
$scope.changeEdit = function(binding) {
binding.onEdit = true;
//$scope.editNum = newNum;
$scope.showSave = true;
};
$scope.saveEverything = function() {
var error = false;
angular.forEach($scope.macbindings, function(binding) {
if(binding.onEdit) {
if (validateBinding(binding)) {
binding.onEdit = false;
} else {
error = true;
}
}
});
if (error) {
alert("One/some of the value you are editing need to be greater than 100");
} else {
$scope.showSave = false;
}
}
You can check the updated fiddle for the same,
https://jsfiddle.net/balasuar/by0tg92m/27/
Note: As you are using angular, you can validate the model as above and no need to retrieve and loop the input elements for the validation. Also for your case, validating the model is sufficient.
If you need some advanced validation, you should create a custom
directive. Since, playing around with the elements inside the
controller is not recommended in AngularJS.
You can use a custom class for those inputs you want to validate. Then you can select all those inputs with that class and validate them. See this Fiddle https://jsfiddle.net/lealceldeiro/L38f686s/5/
$scope.saveEverything = function() {
var inputs = document.getElementsByClassName('inputCtrl'); //inputCtrl is the class you use to select those input s you want to validate
$scope.totalInputs = inputs.length;
$scope.invalidCount = 0;
for (var i = 0; i < inputs.length; i++){
if(inputs[i].value.length < 100){
$scope.invalidCount++;
}
}
//do your stuff here
}
On line 46 a get all the inputs with class "classCtrl" and then I go through the input s array in order to check their length.
There you can check if any of them is actually invalid (by length or any other restriction)

Store formatting information in an array then apply it to a range

I'm trying to create a script that will automatically format a selection based on the formatting of a table in another sheet. The idea is that a user can define a table style for header, rowOdd and rowEven in the Formats sheet, then easily apply it to a selected table using the script.
I've managed to get it working, but only by applying one type of formatting (background colour).
I based my code for reading the code into an array on this article.
As you will hopefully see from my code below, I am only able to read one formatting property into my array.
What I would like to do is read all formatting properties into the array, then apply them to the range in one go. I'm new to this so sorry if my code is a mess!
function formatTable() {
var activeRange = SpreadsheetApp.getActiveSpreadsheet().getActiveRange(); //range to apply formatting to
var arr = new Array(activeRange.getNumRows());
var tableStyleSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Formats"); //location of source styles
var tableColours = {
header: tableStyleSheet.getRange(1, 1, 1).getBackground(),
rowEven: tableStyleSheet.getRange(2, 1, 1).getBackground(),
rowOdd: tableStyleSheet.getRange(3, 1, 1).getBackground()
}
for (var x = 0; x < activeRange.getNumRows(); x++) {
arr[x] = new Array(activeRange.getNumColumns());
for (var y = 0; y < activeRange.getNumColumns(); y++) {
x == 0 ? arr[x][y] = tableColours.header :
x % 2 < 1 ? arr[x][y] = tableColours.rowOdd : arr[x][y] = tableColours.rowEven;
Logger.log(arr);
}
}
activeRange.setBackgrounds(arr);
}
Thanks!
I might be wrong but based from the list of methods given in Class Range, feature to save or store formatting details currently do not exist yet.
However, you may want to try using the following:
copyFormatToRange(gridId, column, columnEnd, row, rowEnd) or copyFormatToRange(sheet, column, columnEnd, row, rowEnd) wherein it copies the formatting of the range to the given location.
moveTo(target) wherein it cuts and paste (both format and values) from this range to the target range.
Did you know that you can get all of the different formatting elements for a range straight into an array?
E.g.
var backgrounds = sheet.getRange("A1:D50").getBackgrounds();
var fonts = sheet.getRange("A1:D50").getFontFamilies();
var fontcolors = sheet.getRange("A1:D50").getFontColors();
etc.
However, there's no way to get all of the formatting in one call unfortunately, so you have to handle each element separately. Then you can apply all of the formats in one go:
targetRng.setFontColors(fontcolors);
targetRng.setBackgrounds(backgrounds);
and so on.

Resources