Xcode>Instruments>Automation>Mac: is there a way to use regular expression within Automation in Instruments - xcode-instruments

I am totally new to Instruments>Automation. Trying to test the internal app using Automation in Instruments.
Here is my problem:
Our app has the UI cells generated on the fly. There is no way to predict how many cells will be created and what name they will have. But, all of them will contain a certain string (like "Courses"). The question is - How, using Automation, find out if particular cell contain that string in its name?

You are able to get total cells count simply using "length" property.
var cellsCount = <YourUIATableViewObject>.cells().length;
UIALogger.logMessage("total cells count = " + cellCount);
After that you will be able to get cell properties and operate with them:
for (var i = 0; i < cellsCount; i ++)
{
var cellValue = <YourUIATableViewObject>.cells()[i].value();
var cellName = <YourUIATableViewObject>.cells()[i].name();
UIALogger.logMessage("Cell #"+i+" properties: cellValue ="+cellValue+"; cellName ="+cellName);
//Try to use match() or search() functions to find what you need.
if ( cellName.search("Courses") != -1 )
//if (cellValue.search("Courses") != -1 )
{
UIAlogger.logMessage("Cell #"+i+" contains 'Courses'");
}
else
{
UIAlogger.logMessage("Cell #"+i+" does not contain 'Courses'");
}
}
This JavaScript tutorial will help you:

Related

get value for specific question/item in a Google Form using Google App Script in an on submit event

I have figured out how to run a Google App Script project/function on a form submit using the information at https://developers.google.com/apps-script/guides/triggers/events#form-submit_4.
Once I have e I can call e.response to get a FormResponse object and then call getItemResponses() to get an array of all of the responses.
Without iterating through the array and checking each one, is there a way to find the ItemResponse for a specific question?
I see getResponseForItem(item) but it looks like I have to somehow create an Item first?
Can I some how use e.source to get the Form object and then find the Item by question, without iterating through all of them, so I could get the Item object I can use with getResponseForItem(item)?
This is the code I use to pull the current set of answers into a object, so the most current response for the question Your Name becomes form.yourName which I found to be the easiest way to find responses by question:
function objectifyForm() {
//Makes the form info into an object
var myform = FormApp.getActiveForm();
var formResponses = myform.getResponses()
var currentResponse = formResponses[formResponses.length-1];
var responseArray = currentResponse.getItemResponses()
var form = {};
form.user = currentResponse.getRespondentEmail(); //requires collect email addresses to be turned on or is undefined.
form.timestamp = currentResponse.getTimestamp();
form.formName = myform.getTitle();
for (var i = 0; i < responseArray.length; i++){
var response = responseArray[i].getResponse();
var item = responseArray[i].getItem().getTitle();
var item = camelize(item);
form[item] = response;
}
return form;
}
function camelize(str) {
str = str.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()#\+\?><\[\]\+]/g, '')
return str.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function(match, index) {
if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces
return index == 0 ? match.toLowerCase() : match.toUpperCase();
});
}
//Use with installable trigger
function onSubmittedForm() {
var form = objectifyForm();
Logger.log(form);
//Put Code here
}
A couple of important things.
If you change the question on the form, you will need to update your
code
Non required questions may or may not have answers, so check if answer exists before you use it
I only use installable triggers, so I know it works with those. Not sure about with simple triggers
You can see the form object by opening the logs, which is useful for finding the object names

Stock Inventory - Send email when cell value < 2 (Google Spreadsheet)

I currently trying to create for stock inventory of some products that are frequently used in my workplace using google spreadsheet. Moreover, I'm trying to come up with a script that would send me an email when a certain product reaches a value below 2 so that I would know that a certain product needs to be restock. I'm do not know the basics of coding, but here's what I got so far:
function readCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var ProductA = sheet.getRange("B2").getValue();
var Product B = sheet.getRange("B3").getValue();
var min = 2
if (ProductA<min) MailApp.sendEmail('n********#googlegroups.com', 'LOW REAGENT STOCK', 'Attention! Your stock of ProductA is running low. Please proceed to restock.');
if (ProductB<min) MailApp.sendEmail('n********#googlegroups.com', 'LOW REAGENT STOCK', 'Attention! Your stock of ProductB is running low. Please proceed to restock.');
}
I put the trigger on onEdit to run the script and I intent to expand the list with more products. The thing is that if one product as already reached a value below 2 and if a change another one, the script will send email for both of them. With more products, this becomes a nuisance, because I would received a bunch of emails if other values remain below 2. Can someone help me out with this? I couldn't find any solution to this so far and I would truly appreciate some help.
Thank you!
When the "onEdit" trigger fires, it receives the event object as parameter containing some useful information about the context, in which the edit action occurred.
For example,
function onEdit(e) {
// range that was edited
var range = e.range;
//value prior to the edit action
var oldValue = e.oldValue;
//new value
var value = e.value;
//sheet the action came from
var sheet = range.getSheet();
//cell coordinates (if edited range is a single cell)
//or the upper left boundary of the edited range
var row = range.getRow();
var col = range.getColumn();
}
You can inspect the event object to get the cell that was edited and see if it's in column B.
var productsColIndex = 1; //column A index;
var inventoryColIndex = 2; //column B index
var range = e.range;
var value = e.value;
var sheet = range.getSheet();
var editedRow = range.getRow();
var editedCol = range.getColumn();
var productName = sheet.getRange(editedRow, productsColIndex).getValue();
//checking if
//1) column B was edited
//2) the product exists in column A
//3) new value is less than 2
if ((editedCol == inventoryColIndex) && productName && value < 2) {
//code for sending notification email.
}
Finally, because simple triggers like onEdit() can't call services that require authorization, it's better to create a function with a different name and then set up the installable trigger manually. In your Script Editor, go to "Edit" -> "Current project's triggers" -> "Add a new trigger" , select your function name from the dropdown list, and pick the following options: "From spreadsheet", "On edit".

Sort/Order an Undetermined Number of Columns (LINQ\Entity Framework)

Need to sort/order a list of data based on an undetermined number of columns (1 or more).
What i'm trying to do is loop through the desired columns and add an OrderBy or ThenBy based on their number to the query'd list, but i'm unsuccessful...
Done this, but it doesn't compile:
var query = GetAllItems(); //returns a IQueriable list of items
//for each selected column
for (int i = 0; i < param.Columns.Length; i++)
{
if (i == 0)
{
query = query.OrderBy(x => x.GetType().GetProperty(param.Columns[i].Name));
}
else
{
//ERROR: IQueriable does not contain a definition for "ThenBy" and no extension method "ThenBy"...
query = query.ThenBy(x => x.GetType().GetProperty(param.Columns[i].Data));
}
}
How can i resolve this issue? Or any alternative to accomplish this requirement?
SOLUTION: #Dave-Kidder's solution is well thought and resolves the compile errors i had. Just one problem, OrderBy only executes (actually sorts the results) after a ToList() cast. This is an issue because i can't convert a ToList back to an IOrderedQueryable.
So, after some research i came across a solution that resolve all my issues.
Microsoft assembly for the .Net 4.0 Dynamic language functionality: https://github.com/kahanu/System.Linq.Dynamic
using System.Linq.Dynamic; //need to install this package
Updated Code:
var query = GetAllItems(); //returns a IQueriable list of items
List<string> orderByColumnList = new List<string>(); //list of columns to sort
for (int i = 0; i < param.Columns.Length; i++)
{
string column = param.Columns[i].Name;
string direction = param.Columns[i].Dir;
//ex.: "columnA ASC"
string orderByColumn = column + " " + direction;
//add column to list
orderByColumnList.Add(orderBy);
}
//convert list to comma delimited string
string orderBy = String.Join(",", orderByColumnList.ToArray());
//sort by all columns, yay! :-D
query.OrderBy(orderBy).ToList();
The problem is that ThenBy is not defined on IQueryable, but on the IOrderedQueryable interface (which is what IQueryable.OrderBy returns). So you need to define a new variable for the IOrderedQueryable in order to do subsequent ThenBy calls. I changed the original code a bit to use System.Data.DataTable (to get a similar structure to your "param" object). The code also assumes that there is at least one column in the DataTable.
// using System.Data.DataTable to provide similar object structure as OP
DataTable param = new DataTable();
IQueryable<DataTable> query = new List<DataTable>().AsQueryable();
// OrderBy returns IOrderedQueryable<TSource>, which is the interface that defines
// "ThenBy" so we need to assign it to a different variable if we wish to make subsequent
// calls to ThenBy
var orderedQuery = query.OrderBy(x => x.GetType().GetProperty(param.Columns[0].ColumnName));
//for each other selected column
for (int i = 1; i < param.Columns.Count; i++)
{
orderedQuery = orderedQuery.ThenBy(x => x.GetType().GetProperty(param.Columns[i].ColumnName));
}
you should write ThenBy after OrderBy like this:
query = query
.OrderBy(t=> // your condition)
.ThenBy(t=> // next condition);

Reformatting spreadsheet responses into a new tab on form submit

Here are my spreadsheet responses from a form: https://docs.google.com/spreadsheets/d/1a9H2HqAwl29IY6-aCvCKs12Xb3vDcZHCOoNugx81PTA/edit#gid=1939572907
The form data generates in the "raw data" tab of the above spreadsheet. However, I'd like to automatically rearrange the form responses in a different format on the "teacher list" tab of the spreadsheet on form submissions. We are trying to keep track of how often we visit a teacher's room and so want all of the timestamps to appear next to the teacher's name.
I do not know if I should be using formulas or a script to get the job done.
To show you our end goal, I have two form submissions that I have typed into the cells where'd we like them to appear on the "teacher list" tab.
Any suggestions or resources to help me accomplish this would be very much appreciated!
This should give you a good start. And, I have removed the merging of the cells in G column in teacher list tab.
function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Raw Data');
var data = sheet.getDataRange().getValues();
var formatSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Teacher List');
var formatData = formatSheet.getDataRange().getValues();
var name = data[sheet.getLastRow()-1][2];
var flag = 0, index;
for(var i=1; i<formatData.length; i++)
{
if(name == formatData[i][0])
{
flag = 1;
index = i;
break;
}
}
if(flag == 1)
{
for(var i=1; i<=5; i++)
{
if(formatData[index][i] == "")
{
formatSheet.getRange(index+1, i+1).setValue(data[sheet.getLastRow()-1][0]);
formatSheet.getRange(index+1, 7).setValue(formatData[index][6].concat('; '+data[sheet.getLastRow()-1][3]));
break;
}
}
}
}
But is there more than 5 visits possible? Is first column of teacher list tab is going to remian same throughout? Do you want to add new row if no match is found for 'Teacher or PLC Observed' from Raw Data with first column of Teacher List tab?
If answer to these questions is positive, you need to tweak a code little bit, try it. I'll help if you're stuck.
Edit: Please set the appscript trigger as: From form -> onSubmit.

Filter getElementsByTagName list by option values

I'm using getElementsByTagName to return all the select lists on a page - is it possible to then filter these based upon an option value, ie of the first or second item in the list?
The reason is that for reasons I won't go into here there are a block of select lists with number values (1,2,3,4,5 etc) and others which have text values (Blue and Black, Red and Black etc) and I only want the scripting I have to run on the ones with numerical values. I can't add a class to them which would more easily let me do this however I can be certain that the first option value in the list will be "1".
Therefore is there a way to filter the returned list of selects on the page by only those whose first option value is "1"?
I am pretty sure that there is a better solution, but for the moment you can try something like:
var allSelect = document.getElementsByTagName("select");
var result = filterBy(allSelect, 0/*0 == The first option*/, "1"/* 1 == the value of the first option*/);
function filterBy(allSelect, index, theValue) {
var result = [];
for (var i = 0; i < allSelect.length; i++) {
if(allSelect[i].options[index].value == theValue ) {
result.push(allSelect[i]);
}
}
return result;
}
I managed to get this working by wrapping a simple IF statement around the action to be performed (in this case, disabling options) as follows:
inputs = document.getElementsByTagName('select');
for (i = 0; i < inputs.length; i++) {
if (inputs[i].options[1].text == 1) {
// perform action required
}
}
No doubt there is a slicker or more economic way to do this but the main thing is it works for me.