I'm having a colModel entry like this:
{name:'status', index:'status', sorttype:"text", xmlmap:"STATUS", width:"90", stype: 'select', searchoptions:{sopt: ['eq','ne'], value:':all;Hold:Hold;4-Eye-Check:4-Eye-Check;Approved:Approved;Rejected:Rejected;Closed:Closed'}},
thats working fine as long as it's used in the FilterToolBar, but if I open the NavGridSearch Im running into troubles. The entry "all" is not working anymore. The query in the FilterToolBar seems to ignore my empty but the NavGridSearch doesn't.
Is there any wildcard sign which could be used instead of an empty String, which delivers all entries regardless if I search for all status entries in the FilterToolBar or the NavGridSearch?
I use the newest OpenSource jQGrid Lib(4.3.2)
Thanks in advance!
I am trying to understand the use case for a criteria of 'all'. It seems the purpose of 'all' is that you want the grid to ignore this search criteria and return all rows regardless of this value? If that is the case, why would the user even want to select this search criteria - they can just remove it and the same effect will be achieved. Or am I missing something?
Update
The grid uses function createEl : function(eltype,options,vl,autowidth, ajaxso) to create the select for the search form. Unfortunately this select always adds the all criteria to the list, even though it has a search value of "" which will not match any rows. One workaround is to modify the grid to skip select options that have an empty value. Using the source file jquery.jqGrid.src.js you can add the following code to skip the all option:
else if (sv.length > 1 && sv[0].length === 0) continue;
Here it is within the context of createEl:
if(typeof options.value === 'string') {
so = options.value.split(delim);
for(i=0; i<so.length;i++){
sv = so[i].split(sep);
if(sv.length > 2 ) {
sv[1] = $.map(sv,function(n,ii){if(ii>0) { return n;} }).join(sep);
} else if (sv.length > 1 && sv[0].length === 0) continue; // <-- Change this line
ov = document.createElement("option");
ov.setAttribute("role","option");
ov.value = sv[0]; ov.innerHTML = sv[1];
elem.appendChild(ov);
if (!msl && ($.trim(sv[0]) == $.trim(vl) || $.trim(sv[1]) == $.trim(vl))) { ov.selected ="selected"; }
if (msl && ($.inArray($.trim(sv[1]), ovm)>-1 || $.inArray($.trim(sv[0]), ovm)>-1)) {ov.selected ="selected";}
}
If you need a minified version, update the "src" version of jqGrid and then run it through the Google Closure Compiler.
I am not sure this is a general purpose change, which is why I am calling it a workaround for right now. Longer term a better solution needs to be found so jqGrid can be patched... I'll try to find some more time later to revisit this issue.
Does that help?
Related
I am trying to simplify a C# method that includes the following query:
var matchingDeviceKeys =
from dev in data.Elements("Key1")
where dev.Element("Key2").Element("Key3").Element("VendorID").Value == device.Vendor &&
dev.Element("Key2").Element("Key3").Element("ProductType").Value == device.ProductType &&
dev.Element("Key2").Element("Key3").Element("ProductCode").Value == device.ProductCode
from rev in dev.Element("Key2").Element("Key3").Element("Key4").Elements("MajorRev")
where rev.Attribute("Number").Value == device.MajorRevision &&
rev.Attribute("DefaultMinorRev").Value == device.MinorRevision.ToString(CultureInfo.InvariantCulture)
select dev.Element("Key6").Element("Key7").Element("Key8");
The "rev" target for the second from clause is never used in the select line, making me wonder if that entire second from clause is doing anything. If it is doing something, what is it doing?
My apologies for obfuscating the element names. I have to be careful in sharing proprietary code.
I've created a data validation in apps script for google sheets to prevent the red error flags from popping up. Now I need to control the message box wording. The code I wrote for the message box isn't working.
Here's what I have:
//set data validation
function myFunction() {
var range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('New CI').getRange('A1:AR');
var validation = SpreadsheetApp.newDataValidation().requireTextContains('Edits must be made in the google form').setAllowInvalid(false).build();
range.setDataValidation(validation);
}
//create browser box
function onEdit(e) {
if (
//range A1:AR5000
e.source.getSheetName() == "New CI" &&
e.range.columnStart >= 1 &&
e.range.columnEnd <= 45 &&
e.range.rowStart >= 1 &&
e.range.rowEnd <= 5000
) {
if (e.changetype === 'EDIT' && e.value !== 'Edits must be made in the google form');{
Browser.msgBox('Edits must be made in the google form');
}
}
}
Why don't you just share your spreadsheet in read only mode. And by the way there is no changeType in an onEdit() trigger event object and if you were using the change event it's spelled changeType. It's also not a good idea to put a dialog in an onEdit() simple trigger because they must complete in 30 seconds. So it might be better to consider a toast. But it looks like you don't want people to edit the spreadsheet so just share it with them in read only mode.
The Browser.msgBox works perfectly like this:
function onEdit(e) {
Browser.msgBox('Edits must be made in the google form');
}
In resume, your code runs perfectly, the problem that you are facing is either the if's conditions you have are never satisfied or you are not placing properly the trigger.
First, check the if conditions:
Is it correct the following if condition?
if (e.changetype === 'EDIT' && e.value !== 'Edits must be made in the google form');
What you are saying here is that you will only show the msgBox if the event value is exactly equal to Edits must be made.....
I do not think this is what you want, I believe that you want is that for any edit made on the spreadsheet the msgBox should appear. So, this should be enough:
if (e.changetype === 'EDIT');
Is this first if condition correct?
if (
//range A1:AR5000
e.source.getSheetName() == "New CI" &&
e.range.columnStart >= 1 &&
e.range.columnEnd <= 45 &&
e.range.rowStart >= 1 &&
e.range.rowEnd <= 5000
)
For me it looks okay if what you want is to show the msgBox only when someone edits the cells on the specified range and the specified spreadsheet 'New CI'.
Let me know if this solves your problem.
I´m trying to save a value in spreadsheet's header for later use as a new column value.
This is the reduced version with value (XYZ) in header:
The value in header must be used for new column CODE:
This is my design:
tFilterRow_1 is used to reject rows without values in A, B, C columns.
There is a conditional in tJavaRow_1 to set a global variable:
if(String.valueOf(row1.col_a).equals("CODE:")){
globalMap.putIfAbsent("code", row1.col_b);
}
The Var expression in tMap_1 to get the global variable is:
(String)globalMap.get("code")
The Var "code" is mapped to column "code" but I'm getting this output:
a1|b1|c1|
a2|b2|c2|
a3|b3|c3|
What is missed or there is a better approach to accomplish this escenario ?
Thanks in advance.
Short answer:
I tJavaRow use the input_row or the actual rowN in this case row4.
Longer answer, how I'd do it.
I'd do is let the excel flow in AS-IS. By using some Java tricks we can simply skip the first few rows then let the rest of the flow go through.
So the filter + tjavarow combo can be replaced with a tJavaFlex.
tJavaFlex I'd do:
begin:
boolean contentFound = false;
main
if(input_row.col1 != null && input_row.col1.equalsIgnoreCase("Code:") ) {
globalMap.put("code",input_row.col2);
}
if(input_row.col1 != null && input_row.col1.equalsIgnoreCase("Column A:") ) {
contentFound = true;
} else {
if(false == contentFound) continue;
}
This way you'll simply skip the first few records (i.e header) and only care about the actual data.
i am brand new to LINQ, i currently have a look that loops through all orgs that a user belongs to, to make sure they have permissions to do various operations on the form.
looks something like this:
//loop through all user orgs to see if what they selected, they have access to
foreach (OrgPermission userOrg in user.orgs)
{
//get the org permissions for the selected org
if ((ddlOrg.SelectedValue == (userOrg.Org.orgCode + "-" + userOrg.Org.orgSubCode)))
{
if (userOrg.type.Contains("3") || userOrg.type.Contains("00"))
{
/
/do something here.
}}}
i am trying to get rid of the loop. as if the user has lots of orgs it's taking a little while to run, and i'm trying to optimize application run time.
i tried the following:
bool has = user.orgs.Any(cus => cus.Org.orgCode + "-" + cus.Org.orgSubCode == ddlOrg.SelectedValue);
as you can see, the ddlOrg dropdown value are in org-suborg format. but i'm always getting false.
i would also like to save the result, not in a bool, but possibly as a single user.ORG that it found, so that i can use that to then check permissions and other stuff.
am i on the right track here? could someone please point me in the right direction.
You typically wouldn't get rid of the loop, but rather filter the items that are being looped:
var users = user.orgs.Where(userOrg => ddlOrg.SelectedValue == (userOrg.Org.orgCode + "-" + userOrg.Org.orgSubCode) && (userOrg.type.Contains("3") || userOrg.type.Contains("00")));
foreach(OrgPermission userOrg in users)
{
// do your operation
}
That being said, this is likely not going to be much faster, as the LINQ query is still effectively looping through your items, but it will potentially be simpler to maintain.
If you only need to look for a single OrgPermission (ie: the first), you could speed this up via:
var userOrg = user.orgs.FirstOrDefault(userOrg => ddlOrg.SelectedValue == (userOrg.Org.orgCode + "-" + userOrg.Org.orgSubCode) && (userOrg.type.Contains("3") || userOrg.type.Contains("00")));
// userOrg will be the OrgPermission if found, or null if not.
I have a DataTable, dt, that contains the following:
As you can see, there are two sets of files here: baseline (columns 1-3) and target (columns 4-6). So in this case I have 4 baseline files, m4, m5, m1, and m3 (m1 in row 5 is copied from row 3) and one target file, m1. The problem is that the information for the baseline file m1.txt is duplicated, so I'm trying to remove it using the following LINQ statement:
var extraneousRows = dt.Rows.Cast<DataRow>().
Where(
row => row["BASELINE_FOLDER"] == baselineSubfolder
&& row["BASELINE_FILE"] == baselineFilename
&& row["BASELINE_CHECKSUM"] == baselineChecksum
&& row["STATUS"] == "remove"
).ToArray();
foreach (DataRow dr in extraneousRows)
{
dt.Rows.Remove(dr);
}
This should remove the 3rd row from the DataTable but it doesn't. The code works fine if I omit the && row["STATUS"] == "remove" line, so I know it's functional. And the values for baselineSubfolder, baselineFilename, and baselineChecksum are correct, so that's not the problem.
But for some reason, when I include that line about the status column, it doesn't detect that that row is in the DataTable, even though it clearly is according to the DataSet Visualizer (photo above). So it's never entering the foreach loop and not removing the necessary files. Why???
I maybe should mention that the baseline file information (first 4 rows) are being retrieved from a database, whereas the target file fields are being generated according to user input. I don't see how it would matter where the information is coming from, though, since I'm querying the DataTable directly...
UPDATE
Ok, after following the suggestions of idipous and Jamie Keeling, I've determined that the problem had to do with the foreach loop, which was never being populated. Since this query should only ever return a single row, I eliminated the loop altogether. My revised code looks like this:
var extraneousRows = dt.Rows.Cast<DataRow>().
Where(
row => row["BASELINE_FOLDER"] == baselineSubfolder
&& row["BASELINE_FILE"] == baselineFilename
&& row["BASELINE_CHECKSUM"] == baselineChecksum
&& row["STATUS"] == "remove"
).SingleOrDefault();
dt.Rows.Remove(extraneousRows);
For whatever reason, extraneousRows remains null and that last line is generating a runtime error: IndexOutOfRangeException: The given DataRow is not in the current DataRowCollection
Why isn't this working?
It actually turns out that the problem was that I needed to cast the column values to strings. The solution was incredibly simple: just add a .ToString() after the column names and viola! The following code worked like a charm:
var extraneousRows = dt.Rows.Cast<DataRow>().
Where(
row => row["BASELINE_FOLDER"].ToString() == baselineSubfolder
&& row["BASELINE_FILE"].ToString() == baselineFilename
&& row["BASELINE_CHECKSUM"].ToString() == baselineChecksum
&& row["STATUS"].ToString() == "remove"
).SingleOrDefault();
dt.Rows.Remove(extraneousRows);
I also found a non-LINQ way to do this, by iterating through all the rows of the DataTable. It's not the most efficient, but it works:
for (int z = 0; z < dt.Rows.Count; z++)
{
if ((dt.Rows[z]["BASELINE_FOLDER"].ToString() == baselineSubfolder)
&& (dt.Rows[z]["BASELINE_FILE"].ToString() == baselineFilename)
&& (dt.Rows[z]["BASELINE_CHECKSUM"].ToString() == baselineChecksum)
&& (dt.Rows[z]["STATUS"].ToString() == "remove"))
{
dt.Rows[z].Delete();
}
}
dt.AcceptChanges();