I am trying to achieve the following situation using Data Validation in Google Sheets. I've provided a truncated version of situation in the image below.
I would like to set up data validation in Column B that automatically checks the options in column C (or multiple columns in the same row) to populate the dropdown menu for that row.
I did notice that Google Sheets has an option for formulas in the data validation screen and I tried writing an array formula in this area but I have not been having any luck getting any sort of output.
If it can't be done through this menu I would appreciate any idea how to achieve this through scripts.
One way to achieve this is to select list from a range in the "Criteria" section of the Data Validation editor. Then, select the cells whose values you want to appear in your dropdown.
The only issue is that when you try to fill this down across the column, Google Sheets will not update the criteria range. Say you do the following:
In cell B2, use data validation based on list from a range and select D2:F2 as the criteria range. Now the dropdown in B2 will have the options John's Mom, John's Dad, John's Grandma
Then, fill down or copy this cell down across the whole column
When you open the dropdown for cell B3, it will still have the options John's Mom, John's Dad, John's Grandma
Unfortunately Google Sheets does not currently have a built-in solution for copying/filling data validation references or formulas relatively, as far as I know. But it looks like somebody already wrote a nice script in this Google Docs forum post. To avoid just a link as an answer, I'm going to copy in the script and instructions here. Credit to AD:AM from Google Docs forum.
How to use their script:
Select a range of cells across which you want to copy a data validation rule, relatively
From the Validation+ custom menu, select the appropriate option (all references relative, columns absolute, or rows absolute)
The validation of the upper-left cell will be copied to the rest of the range
Link to original solution's example Google Sheets with script already included - you can save your own copy and then start using.
Or to recreate from scratch, here is the script.
function onOpen()
{
SpreadsheetApp.getActiveSpreadsheet().addMenu
(
"Validation+",
[
{name: "Copy validation (all relative references)", functionName: "copyValidation"},
{name: "Copy validation (relative rows, absolute columns)", functionName: "copyValidationColumnsAbsolute"},
{name: "Copy validation (absolute rows, relative columns)", functionName: "copyValidationRowsAbsolute"}
]
);
}
function copyValidation(rowsAbsolute, columnsAbsolute)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var r = ss.getActiveRange();
var dv = r.getDataValidations();
var dvt = dv[0][0].getCriteriaType();
if (dvt != SpreadsheetApp.DataValidationCriteria.VALUE_IN_RANGE) return;
var dvv = dv[0][0].getCriteriaValues();
Logger.log(dvv);
for (var i = 0; i < dv.length; i++)
{
for (var j = i ? 0 : 1; j < dv[0].length; j++)
{
dv[i][j] = dv[0][0].copy().withCriteria(dvt, [dvv[0].offset(rowsAbsolute ? 0 : i, columnsAbsolute ? 0 : j), dvv[1]]).build();
}
}
r.setDataValidations(dv);
}
function copyValidationRowsAbsolute()
{
copyValidation(true, false);
}
function copyValidationColumnsAbsolute()
{
copyValidation(false, true);
}
I've got an Array with 17 web links of images
var products:Array;
trace(products)
// Ouput :
"http://www.myWebsite.com/zootopia.jpg"
"http://www.myWebsite.com/james.jpg"
"http://www.myWebsite.com/tom.jpg"
..etc
If I do products[10].movieimage; the output will be the 9th link (something like : "http://www.myWebsite.com/lalaland.jpg")
I'm looking for downloading every images without a dialog box.
I manage to do so for 1 image with the specific link, like that :
function saveImage (event:Event):void {
var stream:URLStream = new URLStream();
var image1:File = File.documentsDirectory.resolvePath("test.jpg");
var fileStream:FileStream = new FileStream();
stream.load(new URLRequest("http://www.myWebsite.com/lalaland.jpg"));
stream.addEventListener(Event.COMPLETE, writeComplete);
function writeComplete(evt:Event):void {
var fileData:ByteArray = new ByteArray();
stream.readBytes(fileData,0,stream.bytesAvailable);
fileStream.openAsync(image1, FileMode.UPDATE);
fileStream.writeBytes(fileData,0,fileData.length);
fileStream.close();
trace("writeComplete");
trace(image1.url);
}
}
Question : Is there a way to download all the images with the web links of my products array ? (and if images already exist, replace them. I could use if (image1.exists){ if (image2.exists){ ..etc for each image. But maybe there is a simplier solution)
If you could show me how, with a bit of code, I could that.
Also, note that I'd like to load the images then in Uiloader, like that :
function loadImages():void {
uiloader1.source = image1.url;
uiloader2.source = image2.url;
etc...
}
Don't over think it. You have your array of images. You have your tested routine for saving one image. Now put it together:
Some function initializes things and kicks it off.
Either splice out (or pop out) an item on the array – OR use a index var to access an item in the array
Pass that to your download function.
When the download completes either pop another item off the array OR increment your index. But first you would test if array.length== 0 OR `index > array.length. If either is true (depending on which method you use), then you are done.
If you want to get fancy you can show a progress bar and update it each time your download completes.
I am trying to figure out how to change the default layout to 2 columns from 3 columns. I have been able to do it successfully on every page except for search results. I wouldn't mind changing the default layout to 2 columns as I want it all to be uniform.
Here's the catch, I am on a hosted solution (I hate it, but hey, I am just the developer). I have no access to the file system or individual files. I haven't figured out a way to upload and replace any files, so all changes I make have to be done from the back end. I am really hoping this can be done.
Answer is, you can't. Plain and simple.
However, you can hack the hell out of it using jQuery and get it to work right. Here is the code I used:
//Check for 3 col layout.
if($j('.col3-layout').length>0){
//swap the 3 col layout for the 2 col layout
$j('.col3-layout').addClass('col2-left-layout').removeClass('col3-layout');
//grab all the code in the wapper, and place it in the main
var html=$j('.col-wrapper').html();
$j('.main').html(html);
//If products are shown as a grid, reorder them. If it is a list, leave it alone.
if(!$j('.grid').attr('href')){
//Grab all items in the list, push them into an array, and then remove all the data.
var items=new Array();
$j('.products-grid .item').each(function(){
items.push($j(this).html());
});
$j('.products-grid').remove();
//build your output
var html='';
var gridsize=4; //items per row
for(var i=0;i<items.length;i++){
if(i%gridsize==0){//start a new row
html+='<ul class="products-grid '
if(i/gridsize==0)//very first row
html+='first ';
else if(i==items.length-gridsize)//last row
html+='last '
if(i/gridsize%2==0)//even class
html+='even">';
else
html+='odd">';//odd class
html+='<li class="item first">'+items[i]+"</li>";
}else if(i%gridsize==gridsize-1){//very item in row
html+='<li class="item last">'+items[i]+"</li></ul>";
}else
html+='<li class="item">'+items[i]+"</li>";
}
$j('.category-products').html(html); //populate the data.
}
}
Recently i've been working on a rather modest application, which lists contacts. When a detail-link was clicked, a popup would come up with more details and an image of that contact.
The table this was based on contained a column photo_reference, which held a path to a folder under /i/. With this setup, it was easy to get the images working for each contact.
The popup i showed was a bunch of htmlcode i put in the region footer, and hid.
<div id="contact_popup" class="contact_pop">
<div class="contact_pop_imgcontainer">
<img id="id_photo" class="contact_pop" />
</div>
</div>
When the detail was clicked, i retrieved data via an application process, and showed a modal dialog of this container.
Now the scope has changed: users need to be able to upload their own images. So, i went to work and made it so the images get uploaded into wwv_flow_files, and then i move them to a new contact_image table. So far so good. But now i want to display these pictures, and here i'm kind of stuck.
* I could include a column in my IR, and put a blob format mask on it with image. I've got this working, but annoyingly. My image table has as primary key the field 'ID'. My contacts table also has 'ID' as PK.
Since IMAGE:APXT_CONTACTS_IMG:SMALL_PHOTO:ID::::::inline: specifies ID as the PK, it uses ID from my contacts table.
My link between tables is APXT_CONTACTS.CONTACT_IMAGE_ID -> APXT_CONTACTS_IMG.ID.
The way i might make it work is to rename my id field in the image table to contact_image_id. (why couldnt the format mask just take the column it's based on as the value :().
I then could hide the column, and take the image with javascript to show in my popup. However, this preloads all images for the amount of selected rows, which isn't entirely bad, but i'm looking for an alternative first.
get_blob_file_src also seems no use to me because of the limited use of the parameters (file browse item, id field), and even then, could i use this through an ajax callback?
I'd much rather be able to get the image blob via ajax to then display in my popup, but i have no clue as to how to do this. I've made a stored procedure which gets the file to download and call this from an application process (ajax callback), and with firebug i can see the post/response, but i wouldn't know how to get this displayed as an image.
Javascript:
function cimg(){
var get = new htmldb_Get(null, &APP_ID., "APPLICATION_PROCESS=get_img", &APP_PAGE_ID.);
get.addParam('x01', 25);
var greturn = get.get();
alert(greturn);
var pic = new Image();
pic.onload = function(){
document.body.appendChild(pic);
};
pic.src = greturn;
};
Page process:
begin
show_small_photo(apex_application.g_x01);
end;
Stored Procedure:
create or replace procedure "SHOW_SMALL_PHOTO"
(p_contact_image_id IN NUMBER)
is
v_mime apxt_contacts_img.mime_type%type;
v_length NUMBER;
v_filename apxt_contacts_img.filename%type;
v_lob BLOB;
begin
SELECT mime_type, lengthb(small_photo), filename, small_photo
INTO v_mime, v_length, v_filename, v_lob
FROM apxt_contacts_img
WHERE id = p_contact_image_id;
OWA_UTIL.mime_header (NVL (v_mime, 'application/octet'), FALSE);
HTP.p ('Content-length: ' || v_length);
-- needed?
--HTP.p ('Content-Disposition: attachment; filename="'||v_filename||'"');
OWA_UTIL.http_header_close;
wpg_docload.download_file (v_lob);
end;
(I'd rather not have to grant execute to public and call the stored procedure via a link.)
This way i'd only have to load the pictures of links clicked. Though this code doesn't work. I get the alert and see a bunch of those weird chars, so i presume that is the blob talking. But i'm not getting an image anywhere.
Am i missing something? Doing something wrong? I'm totally out of clues.
Instead of my existing code, i might make this work through creating another page, and juggle page items and their values around to try and get the same layout going, and then get that page through ajax?
I'm mainly trying to minimize impact (=work) on the existing app, so i wouldn't have to yet again change pages.
TL;DR: is it possible to retrieve and display an image blob from a table not in the report query, preferably through ajax?
This is Apex 4.02 on an 11g db
Thanks,
Tom
To whom it may concern, here is how i solved/worked around it:
I went with the fetch-another-page route. Maybe i was too technical or too difficult about it in my op, but in hindsight i think i could've boiled it down to:
"retrieve an image blob via ajax and display it".
So if that rings any bells for anyone, let me know.
Some rectifying too:
my images table is a child of the contacts table, as such my FK between those is images.contact_id -> contact.id
I've created a new page in my application, and put a form in based on my images table. I only display 2 items of the type 'display image' (a thumbnail and original size), and 2 hidden items, 'ID' and 'CONTACT_ID'. I've removed all that was not necessary: no buttons, no DML-process, no labels, no templates.
The automated row fetch process takes as 'primary key' my contact id, so i can call the page with contact_id in the url (so that i won't have to do an extra select to retrieve the correct id in the image table).
On the page i need the pictures, i then get the page with the photos on it when required (ie: when the detail icon is clicked and i show my popup).
Following piece of code is called within this function
(only code 'missing' here is where i call another page process to fetch me contact details in a json format)
//page 120 only holds the 2 images for a contact. Due to images being in
//blobs and no easy way to dynamically fetch them, i made a small
//form with the 2 photos on, and id + contact_id
//(contact_id made PK for the ARF-process, since this is what is worked with)
//The page is pulled in, and the photos retrieved
//htmldb_get does not do the job! It only pulls the page from cache, which isnt what i want
// arrays with the arguments and their values for the post
var vArgs = new Array();
var vVals = new Array();
vArgs.push("P120_CONTACT_ID");
vVals.push(cid);
$.post('wwv_flow.show',
{"p_request" : "NULL",
"p_flow_id" : $v('pFlowId'),
"p_flow_step_id" : "120",
"p_instance" : $v('pInstance'),
"p_arg_names" : vArgs,
"p_arg_values" : vVals},
function(data){
var oContainerSmall = $("#id_photo_container").empty(),
oSmallPhoto = $(data).find("#P120_SMALL_PHOTO").attr({"id":"id_photo",
"alt":oContact.lastname + " " + oContact.firstname}),
oLargePhoto = $(data).find("#P120_LARGE_PHOTO").attr("alt",oContact.lastname + " " + oContact.firstname);
$("#large_photo_container").empty().append(oLargePhoto);
$("#large_photo_container").css({"display": "block", "visibility": "hidden"});
//Why remove and remake the container?
//for some reason i couldn't find out, the image width and height get reset to 0 after
// an initial display of the enlarged picture and closing its dialogbox.
//I assume it is an apex+css+javascript issue.
//The only fix i was able to find was to remove the div and remake a new one.
// There have to be some properties set on the div and/or its children through
// the closing of the popup dialog (for the larger picture),
// which then prevents subsequent calls to get the correct values.
$("#large_photo_container").remove();
var oContainerLarge = $("<div></div>").attr("id","large_photo_container").css({"display":"block", "visibility":"hidden"});
oContainerLarge.append(oLargePhoto);
$("body").append(oContainerLarge);
//Hardcoded value here! Adapt when necessary
if($("#id_contact_type").val() == "Conference Room"){
var oLink = $("<a/>").attr("href", "#")
.click(function(event){
explode_headshot(event, this);
});
oContainerSmall.append(oLink.append(oSmallPhoto));
} else {
oContainerSmall.append(oSmallPhoto);
};
$("#contact_popup").dialog({modal: true,
width: 750,
resizable: false,
title: oContact.lastname + " " + oContact.firstname,
close: function(event, ui){
$("#id_photo").attr({"src": "", "alt": ""});
}});
});
I wouldn't call it ideal, but it works, and that's all i need at this time :)
I made a very similar application for showing contact details including photos a few months ago in apex.
I found this web page very useful:
http://blog.hilandco.com/2010/05/how-to-show-blob-type-column-as-image.html
Displaying an image can be as easy as creating an item of type: "display Image". Settings: " Blob column returned by sql statement".
And then an sql statement selecting the correct row:
select blob_content
from my_bitmap_table
where ID = ...
I am developing a game similar to geochallenge game in facebook. here i am unable to decide whether i should use Image buttons/Grid view/Image view or some other else....?
please can any one suggest in this regard...
My requirement is
I should store some number of images. And at particular time I should randomly display three distinct images, and these images will be replaced by other images when any of those images is clicked. The the images should not be repeated.
can you help me please.
Now i am using Image button concept but the images are repeating in three image buttons. But i should get distinct images on each image button.
after a long struggle I was able to get a solution. Here's what I did.
I have a flags array "Country[]" and three Image Buttons declared as ImageButton array bt[]={id1,id2,id3};, which I use with the following code:
public void randomDisplay()
{
L=Country.length;
for(int i=0; i<3;i++)
{
int random=rand.nextInt(L-1);
if(i==0)
id1=Country[random];
if(i==1)
id2=Country[random];
if(i==2)
id3=Country[random];
id=getResources().getIdentifier(Country[random], "drawable", getPackageName());
bt[i].setImageResource(id);
String temp=Country[L-1];
Country[L-1]=Country[random];
Country[random]=temp;
L=L-1;
}
}
The above code will shift one country name to the end of the country array at each repetition, and decrements the country array length. This will avoid the duplicate names on ImageButtons. If you have any question please let me know...