difference between key value in adressline and getId() value in Google Script - google-apps-script

I wanted to ask what's the difference between the value in the adressline and the id I get when i use getId().
For example for one document the getId() value is:
t8K_TLQPmKzgB72pY4TblUg
while in the adressline the key is:
0Amu7sNvd2IoudDhLX1RMUVBtS3pnQjcycFk0VGJsVWc
what i figured out so far is that when you encode getId in base64 you get more or less the last part of the key in the adressline
(base64Encode(t8K_TLQPmKzgB72pY4TblUg) = dDhLX1RMUVBtS3pnQjcycFk0VGJsVWc=).
But I still don't know what 0Amu7sNvd2Iou stands for, because i have the impression that this parts also is different in older documents, therefore i can't just combine the key using all the time 0Amu7sNvd2Iou at the beginning
Why I need to know this: my scripts use the getId method but some users fill in their ids manually (they just copypaste it from the key from the adressline). The result is that when i try to compare them although they refer to the same document i can't match them like they are completly different...
thanks a lot for bringing light into this problem
edit #taras:
i can also open the document with the key and the id. It's just weird that there are kind of two different id's for one document. If for example i want to compare if a value somebody copypasted from the adressline to a document is the same as the file i have opened i won't get a true, even it is the same file
var keyFromHeadline = "0Amu7sNvd2IoudDhLX1RMUVBtS3pnQjcycFk0VGJsVWc"
var id = SpreadsheetApp.getActiveSpreadsheet.getId();
if (keyFromHeadline==id) Browser.msgBox("blabla")
Therefore i would be interested what is the reason for the two different values and how i could match them

If you need to have unique file IDs just normalize them. Everytime a user enters an ID manually just run it trough the fileIdNormalize function:
function fileIdNormalize(id) {
if (typeof id == 'string' && id.length > 0)
return DocsList.getFileById(id).getId();
return '';
}

Just a suggestion :
Since base64Encode seems to give you a significative part of the adress url you could use a match to check if the document is the same.
Something like :
if('manually_entered_key'.match(base64Encode('the_value_obtained_by_getId')==base64Encode('the_value_obtained_by_getId')){
// consider as the same doc ...

Related

Indexeddb sorting with multiple indexes

I have a file object store by indexing name and library_id like below,
let objectStore = db.createObjectStore('file', { keyPath: 'id' });
tempStore.createIndex('nameLibId', ['attributes.name', 'attributes.library_id'], { unique: false });
The object store contains multiple library id's files. I'd like apply the name sort to the particular library id's files. I tried indexing in the below format but it returns empty data.
let self = this,
db = get(self, 'db'),
transaction = db.transaction(["file"], "readonly"),
objectStore = transaction.objectStore("file"),
index = objectStore.index('nameLibId'),
keyRange = IDBKeyRange.only('library_id')),
req = index.getAll(keyRange);
req.onsuccess = ((e)=>{
console.log(e.target.result); // returns empty array
});
Attached the screenshot of db model for reference.
24536475, abc, created, jhgf and lastmodified file names are belongs to a library id called 123.
Screen Shot..* file names are belongs to an another library id called 234.
I need the files which are sorted by name only the given library id. Any help would be highly appreciated.
If your index is based on a properties array and you want to match something using IDBKeyRange.only, then your parameter to IDBKeyRange.only should also be an array. Right now you are comparing a basic string value against a properties array value, where of course nothing matches. In other words, you cannot query against a two-part array using only one part of it.
Furthermore, the parameter to IDBKeyRange.only isn't a property name, it is a value. You want to specify a value to match in the index's set of keypath values. For example, if your index was based exclusively on attributes.name, then you would want to specify a particular value within that index, such as "abc".
And so, taking into account the above two points, and given that your index is not a single value but is instead an array of two properties, you need to revise your parameter to IDBKeyRange.only to look for an array. Something like IDBKeyRange.only(['abc', 'yoktc....']);.
Now, this is further complicated by the fact that what you are doing in your code does not actually accomplish what you want. Ignoring the sort concern for a moment, you only want to use the id condition, and not the name, when matching rows of this index. So you might be tempted to try IDBKeyRange.only([undefined, 'asdf']). Unfortunately this will not work at all because you cannot specify undefined (you will get a javascript error).
So, you must always query by both values, even though you only want to apply criteria to one of the values. The trick here is that you switch to using a different method than only. You use IDBKeyRange.bound(), and furthermore, you do a trick where you specify a criteria such as "smallest possible number is less than my number and my number is less than largest possible number", e.g. a condition that always is true. You use "smallest possible value" as your lower boundary, and "largest possible value" as your upper boundary.
Here is an example in your case. The smallest possible value of name I think is empty string. The largest possible value of name is probably any non-alphanumeric character, so let's use tilde "~". So, now we would rewrite the range parameter. Instead of using IDBKeyRange.only, we use IDBKeyRange.bound. It looks like the following (roughly):
var libId = ???;
var smallestNameValue = '';
var largestNameValue = '~';
var lowerBound = [smallestNameValue, libId];
var upperBOund = [largestNameValue, libId];
var range = IDBKeyRange.bound(lowerBound, upperBound);
Now, the second part, regarding sorting, and a major caveat of using indices that have multiple parts (not to be confused with the multiPart index property, ugh). And I myself get this backwards all the time, so I might even be wrong here and the above will work. The problem with the above is that one the first criterion is met the second is ignored, because of how the short-circuited array sorting algorithm works in indexedDB's comparison function. Your query is going to match everything, because every index row meets the criteria. So the trick to this is to always query first by the important condition, to basically pay attention to the order in which you specify your conditions. So what that means is that you need to switch the order of the properties you specified when creating the index, so that you can query first by libId and then by name.
Instead of createIndex('nameLibId',['attributes.name','attributes.library_id']); you want to do createIndex('nameLibId',['attributes.library_id', 'attributes.name']);. And this also means you need to swap your lower and upper bound queries, e.g. var lowerBound = [libId, smallestNameValue]; (and don't forget to switch the upper).
As I mentioned in my answer on using compound indices, you can always using indexedDB.cmp to experiment. Right now, open up the console on this web page. In the console, type something like this:
indexedDB.cmp(['', '5'], ['~', '5']);
Take a look at the results.
Some final notes:
Tilde might be the wrong thing to use, sorry but I am not bothering to remember, you could also just try any valid sentinel value, where by sentinel I mean any value you know will always come after all your other valid values
As I point out in my other answer, if either prop is missing in the data the actual object won't match
for cmp, -1 means left is less than right, 0 means left equals right, and 1 means left greater than right

Google Spreadsheet, Substitute Integer with String

Hey there and thanks in advance.
I'm exporting the API of an application onto my spreadsheet, which works fine. Due to how the API was programmed however, some of the columns now contain the TypeID (an integer representing the "name") and not the actual name. I know what TypeID represents what Name, so what I'm looking for is a way to substitute all entries of said column with the actual name.
I have already begun to make a humongus switch case in the script editor that just checks every cell in that column and based of the contents substitues the right name, but as you can probably imagine that would take a while.
Just wondering if there is a "cleaner" and more effective way.
I'd recommend making a JSON object to represent your switch case and call that
i.e :
var jsonMap = {"TYPEID":"NAME"};
Then call :
jsonMap[fieldValue]
To return the correct value for that field
You could have the script trigger on row modification and have it translate that way.
Alternatively I'd recommend mapping the field before it is exported into sheets using the language you're exporting in and have the data enter the sheet correctly

I can't get an e-mail of a specific contact

Here is my story:
I'm writting a script that permits to see every users in an array of group (I mean, you select 2 group, it show every users in one of these two groups). It also do some other treatment. But it's OK for this part.
Everything seems to work correcly. Except for only one user.
The idea is, I have to get the e-mail of a user, to then compare users'e-mail got in a former group, to see if this user is (or not) already listed ( in order to avoid duplicate).
The user (this one only) won't use my function. I supposed it was a group, but it really is a user.. I'm pretty sure it is an option to select ( or not) in the user's preference, but which one?
PS: here is the error quote
TypeError: Fonction getEmail introuvable dans l'objet
(TypeError: getEmail function not found in object)
And here is the code I use in order to get e-mails:
for(var i in objuser){
for(var j in objuser[i])
{
objuser[i][j]=objuser[i][j].getEmail();
}
}
Objuser is a list of User Object. First dimension (I) is the group, second dimension (j), is users of the "I" group.
PROBLEM NOT SOLVED:
the reason:
I have 2 functions that do treatments. Theses Two function need an array, that another function create (which is long to execute). My code is done in such a way, if i execute consecutively these 2 treatment functions with the same array, the second to be played use an incorrect array.
So i clone it with :
var groupsUser2 = JSON.parse(JSON.stringify(groupsUser));
but, now that i dont use anymore email adresses ( i mean String), but direct Users (i mean Object), the former code don't clone correctly:
array1 : user's array (Objects)
array2 = JSON.parse(JSON.stringify(array1))
log(array1) :[blabla1#...com,blabla2#...com,blabla3#...com, .....]
log(array2) :[{},{},{}………]
SO.... Here is the new question: Is there a simple way to copy an Object's array ?
Here is the former question: What rights configuration unallow me to use the getEmail() function for a specific contact?
I need an answer just for one of these two questions, and i'll be able to correct my problem. Any idea guys???????
never use "for x in array" its bad use of javascript on an array because the array has the "length" property which is a number and not the object your loop expects.
instead use " for (i=0;...." or forEach.
Well, I was using getEmail() function in order to compare users got in one group, to others got in another group , so that i can avoid duplicates.
I was checking with IndexOf() if the user adress were in the array of the other group's users.
I don't know why , but now it works even if i don't get the e-mail of the user. So , the problem that was happening for one user can't happen anymore.
Conclusion: Problem solved. Thx mates
I thought about a solution: try .. catch, so that the email which won't be get, will be potentially duplicated because I will not be able to find the user if already displayed or not without his e-mail, but at least the script will not crash.

magento table "sales_flat_order" field "protect_code" explanation

We are working on magento database and tables. Magento seems to write a code in table sales_flat_order field protect_code to define if there is a invoice or a shipment done already. It would look something like
01b335 or
a0a243
But there is no key to understand what this protection code means. Is there an explanation of the meaning of these codes and how they are generated?
Where is it generated?
If you look in app/code/core/Mage/Sales/Model/Order.php on around line 2052, you will find the following:
$this->setData('protect_code', substr(md5(uniqid(mt_rand(), true) . ':' . microtime(true)), 5, 6));
This is where protect_code is generated for the order (using a combination of md5, uniqid, and random integer.
What is it used for?
If you look in app/code/core/Mage/Sales/Helper/Guest.php and find the loadValidOrder function. You will see protect_code used in some areas to ensure the order being loaded is the correct one for the guest's cookie value.
It's also used in other areas, such as tracking information comparisons. You can see several instances of the getProtectCode() method being called in the Shipment models to compare the order to the tracking information. An example of a function that uses it is:
public function getTrackingInfoByTrackId()
{
$track = Mage::getModel('sales/order_shipment_track')->load($this->getTrackId());
if ($track->getId() && $this->getProtectCode() == $track->getProtectCode()) {
$this->_trackingInfo = array(array($track->getNumberDetail()));
}
return $this->_trackingInfo;
}
As you can see with $this->getProtectCode() == $track->getProtectCode(), the tracking protect_code must match the Shipment protect_code.

Nil error when trying to call a function in Lua

I'm getting a strange error that I can't for the life of me crack.
I'm coding a card game and I have two tables of different lengths. One links entries to functions, and the other holds the played cards. The first table is for attributes that certain cards in the deck have.
ATTRIBUTES = {
Reset = RuleBook.Do_Reset,
Go_Lower= RuleBook.Do_Go_Lower,
Mirror = RuleBook.Do_Mirror}
The way these functions are called is as follows:
ATTRIBUTES[cardPile[#cardPile].Attribute]()
I've printed out of contents of both the card object and the ATTRIBUTES table and both are completely in tact. Cards that have an attribute have a table entry under Attribute for a function, and those link up to the Do_... functions. Yet the above line of code doesn't appear to work. If anyone has ideas or suggestions they'd be appreciated.
Lua lets you basically use any kind of lua value as a key in a table. The problem with your code above is that your ATTRIBUTE table uses strings as the key but cardPile[#cardPile].Attribute is a function NOT a string.
When you perform the lookup here:
ATTRIBUTES[cardPile[#cardPile].Attribute]()
You're saying lookup the corresponding value in ATTRIBUTES having the key cardPile[#cardPile].Attribute which is a function. Your ATTRIBUTES table as you have it defined only contain strings as keys -- it has no functions as keys so nil is returned.
Two possible fixes for this:
Assuming cardPile's Attribute field already refers to the function you want, you can just call it like this:
cardPile[#cardPile].Attribute()
The alternative is to change how you setup card_obj's Attribute field -- make it refer to a string instead of the the function:
function Card.Create(Suit, Number, Name)
local card_obj = {}
-- ...
if( card_obj.number == 1 ) then
card_obj.Attribute = "Reset"
elseif( card_obj.number == 6 ) then
card_obj.Attribute = "Go_Lower"
-- ... etc.
else
card_obj.Attribute = nil;
end
end