cfspreadsheet and modifing tab contents, getting tab exists on update - coldfusion

I am attempting to read a 'named tab' of a spreadsheet into a table, update the values, then save them back to the same tab I am trying to see if its just me or something odd in the spreadsheet functions, pseudo code follows. ( I don't think I am having a coding problem but a cf limitation? specific cold withheld (may add later) )
cfspreadsheet read sheetname query
dump query -- ok
update query and dump -- ok
cfspreadsheet update sheetname query -- fail, already has sheet with sheetname -duh-
(also cfspreadsheet write -- fails)
to get this to work I had resorted to
read tab
modify tab
read workbook -- new var
delete sheet -- new var
saveworkbook -- new var -- disk edition now sans tab..
update workbook add sheet -- using var holding just the modified tab
-- this seems to be horribly resource intensive ... and just plain silly
Forta example seems to be for single sheet workbooks only.
Thanks in advance.
Gary
-- update: Rather than using the tags I switched to functions in script.
No use of query object.
all cf implementation of POI
Cleaner solution follows ... actual code
<cfscript>
// read workbood; set active sheet
sObj = SpreadsheetRead(expectedLocWName);
SpreadsheetSetActiveSheet(sObj, 'Version');
// internal code removed spreadsheet getcellvalue
// update
spreadsheetsetcellvalue(sObj, fileVersionNext, 5, 2 );
var overWriteMe = true;
spreadsheetwrite(sObj, expectedLocWName, overWriteMe);
</cfscript>

The action is just poorly named. Per the docs: update - adds a new sheet to an existing XLS file. You cannot use the uppdate [sic] action to change an existing sheet in a file.
to get this to work I had resorted to
If you do not limit yourself to cfspreadsheet only, you should be able to "update" a sheet by reading in the file, with SpreadsheetRead. Then delete the sheet, and add/recreate it.
Technically you could skip the delete/recreate process and simply modify the existing sheet in place. Just read in the file, set the sheet you want to modify as active, then make your changes. However, depending on the modifications, it is often simpler to just delete the sheet and insert a new one.

Related

Building app to upload CSV to Oracle 12c database via Apex

I'v been asked to create an app in Oracle Apex that will allow me to drop a CSV file. The file contains a list of all active physicians and associated info in my area. I do not know where to begin! Requirements:
-after dropping CSV file to apex, remove unnecessary columns
-edit data in each field, ie if phone# > 7 characters and begins with 1, remove 1. Or remove all special characters from a column.
-The CSV contains physicians of every specialty, I only want to upload specific specialties to the database table.
I have a small amount of SQL experience from Uni, and I know some HTML and CSS, but beyond that I am lost. Please help!
Began tutorial on Oracle-Apex. Created upload wizard on a dev environment
User drops CSV file to apex
Apex edits columns to remove unneccesary characteres
Only uploads specific columns from CSV file
Only adds data when column "Specialties" = specific specialties
Does not add redundant data (physician is already located in table, do nothing)
Produces report showing all new physicians added to table
Huh, you're in deep trouble as you have to do some job using a tool you don't know at all, with limited knowledge of SQL language. Yes, it is said that Apex is simple to use, but nonetheless ... you have to know at least something. Otherwise, as you said, you're lost.
See if the following helps.
there's the CSV file
create a table in your database; its description should match the CSV file. Mention all columns it contains. Pay attention to datatypes, column lengths and such
this table will be "temporary" - you'll use it every day to load data from CSV files: first you'll delete all it contains, then load new rows
using Apex "Create page" Wizard, create the "Data loading" process. Follow the instructions (and/or read documentation about it). Once you're done, you'll have 4 new pages in your Apex application
when you run it, you should be able to load CSV file into that temporary table
That's the first stage - successfully load data into the database. Now, the second stage: fix what's wrong.
create another table in the database; it will be the "target" table and is supposed to contain only data you need (i.e. the subset of the temporary table). If such a table already exists, you don't have to create a new one.
create a stored procedure. It will read data from the temporary table and edit everything you've mentioned (remove special characters, remove leading "1", ...)
as you have to skip physicians that already exist in the target table, use NOT IN or NOT EXISTS
then insert "clean" data into the target table
That stored procedure will be executed after the Apex loading process is done; a simple way to do that is to create a button on the last page which will - when pressed - call the procedure.
The final stage is the report:
as you have to show new physicians, consider adding a column (into the target table) which will be a timestamp (perhaps DATE is enough, if you'll be doing it once a day) or process_id (all rows inserted in the same process will share the same value) so that you could distinguish newly added rows from the old ones
the report itself would be an Interactive report. Why? Because it is easy to create and lets you (or end users) to adjust it according to their needs (filter data, sort rows in a different manner, ...)
Good luck! You'll need it.

SP 2013 - Quick edit with Managed Meta Data columns, copy and paste from excel

I'm trying to migrate a meta data from an excel spreadsheet to a SP 2013 document library. The columns are managed meta data columns with pre defined terms matching the data in the excel spreadsheet.
However I cannot copy and paste data from excel via Quick Edit in the doucment library without getting the following error "The data returned from the tagging UI was not formatted correctly"
This happens even when I remove all formatting or paste to notepad first.
Are there any simple solutions to this issue?
http://i.imgur.com/1bqpMPA.jpg
Thanks,
Any metadata fields are in fact foreign keys, as it were, to a dynamic, hidden table (or 'list', whatever you want to call it) within SharePoint. To paste a value into a metadata column, you need to know your element's guid (as in, within the term set) and then append that to each metadata element you're pasting in as a <name>|<guid> pair.
Getting the GUID for an element within your term set
Browse to [site-root]/TaxonomyHiddenList/AllItems.aspx and create a new view (or edit the default one) to display the field 'IdForTerm'.
Where you have a term 'apple', your IdForTerm may look like '1288beaf-82e0-4d81-b9de-ad5ad8382938'. Take a note of the guid for each term which appears within your input data.
Edit your input to correctly reference each term
Let's say you're importing your data from an Excel spreadsheet. Or from a CSV. It doesn't really matter. What you need to do is, basically, a find and replace down each managed metadata column, replacing 'term' with 'term|guid'. So our example from earlier, with the apple, would become 'apple|1288beaf-82e0-4d81-b9de-ad5ad8382938'.
Finally, assuming your view is set up in exactly the same order as your input data, you should be able to 'edit list' from within the browser, hit the leftmost side of your first input row (to select the entire row) and CTRL+V all of your data at the same time.
Note there appears to be a limit to the number of entries you can make at the same time. It appears to sit at around 5,000 elements.
Adding on to #rmacd's answer, you can also get the GUID for a given MMS term by first manually entering the value(s) you need in a Quick Edit cell, then copy and paste the same value(s) from SharePoint to Excel. The pasted value will appear with the full term|guid that you need to complete the bulk copy/paste.

Copy Records in Oracle Apex

I need to copy selected row values and store as a new record.
I am using Oracle Apex 4.2 and Tabular Form.
I need to use checkbox to select the rows and button copy. When i select multiple rows followed by click copy button to copy all the selected row values as new rows and save.
Can anyone Help
Copying Records Through an APEX Tabular Form Input
The idea of cloning existing records from a single table through an Oracle APEX Tabular Form works without much interference with the default design that you can set up through the APEX wizard for page region content.
Build a table with an independent primary key.
Suggested to include two auxiliary columns: COPY_REQUEST and COPIED_FROM for running copy operations. Specific form elements will map to these columns on the tabular form that will be set up.
Build an Oracle stored procedure that can read which records need to be copied. This procedure will be invoked each time the SUBMIT button is pressed.
(optional) Consider including a suppression of step (3) in the event that there is nothing to process (i.e., no records marked for copying).
The Working Table for Receiving Input: COPY_ME
TIP: You will have an easier time if you use the standard TABLE creation wizard. Designate CUSTOMER_ID as the PRIMARY_KEY and have APEX create its standard auto-incrementing functionality on top. (sequence plus trigger set up.)
Here's the sample data I used... though it doesn't matter. You can put in your own values and be able to verify what happened easily.
The Heavy Lifting: The Stored Procedure for Cloning Records in COPY_ME
This procedure works with 1 or more records at a time with a special identifier in the COPY_REQUEST table. After the task is done, the procedure cleans up and resets the request value again.
create or replace procedure proc_copy_me_request is
c_request_code CONSTANT char(1):= 'Y';
cursor copy_cursor is
SELECT cme.CUSTOMER_ID, cme.CUSTOMER_NAME, cme.CITY, cme.COUNTRY,
cme.COPY_REQUEST
FROM copy_me cme
WHERE cme.COPY_REQUEST = c_request_code
FOR UPDATE OF cme.COPY_REQUEST;
BEGIN
FOR i in copy_cursor LOOP
INSERT INTO copy_me (customer_name, city, country, copied_from)
VALUES (i.customer_name, i.city, i.country, i.customer_id);
UPDATE copy_me
SET copy_request = null
WHERE CURRENT OF copy_cursor;
END LOOP;
COMMIT;
END proc_copy_me_request;
There is also a column that can be hidden. It tracks where the record was originally copied from.
Note that the cursor is using the FOR UPDATE OF and WHERE CURRENT OF notation. This is important because the procedure is changing the records that are referenced by it.
APEX Page Setup Instructions
Set up a standard FORM type page and choose the TABULAR FORM style. Follow the set up instructions, taking care to map the correct primary key, and also to the PK sequence object created with the table in the previous steps above.
This is what your page set up will look like after these steps are completed:
EDIT The COPY_REQUEST Form Value:
Under the column attributes section, change the Display As option to "simple checkbox"
Under the list of values section, put a single value under the LOV Definition: Y (case sensitive in either way... just be consistent)
EDIT The COPIED_FROM Form Value:
Under the column attributes section, change the Display As option to "Display as Text(Saves State)". This is just to prevent users from stepping on this read-only field. You could also suppress it if it isn't important to know.
CREATE a New Process: Execute Copy Procedure
This is the bottom of the same configuration page, there are very few things to change or add:
Demonstration: Screenshot of COPY_ME Tabular Form Page in Action
The first screenshot below is before the page is tidied up and the checkbox control is put into place.
Plug in some test data and give it at try. The Page Process created in the step above conditionally invokes the stored procedure that processes all copy requests made at the same time when the SUBMIT form button is selected.
COMMENTS: If you spend enough time tinkering around with the built-in wizards in Oracle APEX, there are opportunities to learn new design patterns and process flows compatible within the tool. Adapting your approach can reduce the amount of additional work and frustration.

Oracle ApexCreate Time field HH:MM

I am having difficulty with a duration field on my form/table.
The users need to indicate in HH:MM how long a meeting took.
What datatype should the column have in the Table. Currently it is TIMESTAMP
How can I make the field have an input mask of 'HH:MM'. What I would like is for the user to be able to type '0130' and the field format it to '01:30' immediately.
Reporting on these times is required so I assume that entering the data as VARCHAR will not help.
Honestly, this is not such an easy subject as people might think it is, and probably more from a user interface point of view than technically.
The easiest way out? The apex datetimepicker. And honestly, if you're new to the technology I'd advise you to use this, especially if you want to steer clear from javascript/jquery initially.
Let's put it this way: the datepicker is fine and works good, but time is really not that fantastic.
Not all that hot right. The value in the input item does not change until you hit 'Close'. The time component seems like a last second sloppy addition honestly. It works, however. (But I'd still set the field to readonly so that a user can not enter text directly.)
Allowing text to be entered means it needs to be validated according to the correct format mask. And format masks differ between those in jQuery (the datepicker) and those in Oracle, and it might be possible that your oracle format mask is not possible in the datepicker, adding even more complexity. There is also no 'live' date validation (nor datetime), there is only the builtin item validation which will check the format mask and which fires on submit.
Anyway, I'd say take a look at it. Set your item to be displayed as a Date Picker, and use the format mask under settings to get the datetime picker:
Now you can push it further of course, though it'll cost some effort. There are several options though.
Personally, when I've implemented date+time I've always split the date from the time in 2 fields. 1 with the date component, and one with the time component, while keeping the item with the original value hidden (so 3 items total). I then use the datepicker on the date item, and use jquery timepicker plugins on the time item. On submit I then add the 2 values together and parse them in a date, and put this value in the original item again (to allow the standard processing to work on items with source set to database column).
One example of a timepicker is here, another one here. They're both not that hard to implement. They have good documentation too. I don't want to dive in the implementation of it here though, I advise you take a look at it first and see how much it scares you. (I'd set up an apex demo but am a bit pressed for time at the moment).
For example, using Trent's (second link) plugin:
put the js file in the apex images directory. I made a folder "/custom" in my case
add the required js files to the page (assuming apex 4.2, put this in javascript file urls)
#IMAGE_PREFIX#libraries/jquery-ui/1.8.22/ui/jquery.ui.slider.js
#IMAGE_PREFIX#custom/jquery-ui-timepicker-addon.js
use onload code such as this to initialize a field
$("#P95_DEPARTURE_TIME").timepicker({hourGrid: 4,minuteGrid: 10});
It'll end up looking as this:
Any further interaction between pickers will need to be handled in javascript code if you want it live. Don't forget server validations.
As for items, my hidden date item has format mask DD-MON-YYYY HH24:MI. Format masks are important, because items are bind variables, and bind variables are varchar2. The value in the html form is also just that, text.
For example, this is on my displayed date item, with a similar setup for the time item:
Then in an after-submit computation I glue the values together again and put them in the m that'll save the value to the database:
:P95_DEPARTURE_DATE_DISP||' '||:P95_DEPARTURE_TIME
This is just a short guide on the setup though, but might be interesting once you're a bit more familiar with the product.
There are also 2 timepicker plugins on apex-plugin, but honestly I don't find them interesting at all when compared to these already existing fine jquery plugins.
Give it some thought and look at it.
If quarters are enough..
item: text field with autocomplete
SELECT ss|| ':' || dd ss_dd
FROM
(SELECT to_char(trunc(sysdate)+(level - 1)/ 24,'HH24')ss
FROM dual CONNECT BY level <= 24),
(SELECT lpad(mod(15 * level, 60), 2, '0') dd
FROM dual CONNECT BY level <= 4)
APEX 4.2: Just to shed some light for any future viewings; now there are loads of Apex plugins for the purpose of picking Date/Time or both returning variations of date time formats as you would required. For e.g. as in your case HH:MM or HH24:MI.
I have personally used TimePicker plugin from http://www.apex-plugin.com which I have no problem in recommending.

Excel Interop: Grouping columns

How do i group columns using Excel interop?
if i record a macro (usually a good way to get started) i get this code:
Columns("I:M").Select
Selection.Columns.Group
unfortunately this doesn't work due to several problems, at least in C++. First of all, Application.Selection returns a normal Range, then Range.Columns is another Range. And Range.Group is this method:
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.range.group%28v=office.11%29.aspx
This method only works in connection with pivot tables.
So how do i create a column group using Excel interop?
Even if i manage to create a group, how can i shrink/expand it? By that i mean clicking on the + to show the content of the group, or rather the other way around, "click" on the minus to hide the group. If i do that while recording a macro, it is not reflected in the macro at all.
Despite the fact that the Range.Group() documentation appears to relate to pivot tables, if you extract the columns using Range.Columns, and then apply the .Group() method to that range, it will have the desired effect. In C#:
Range range = sheet.get_Range("c1","e1");
range.Columns.Group();
Edit: The complete example, again in C# (apologies, it's the example I have handy):
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
app.Visible = true;
app.Workbooks.Add();
Worksheet sheet = app.Workbooks[1].Sheets[1];
Range range = sheet.get_Range("c1","e1");
range.Columns.Group();
One thing the macro recorder obscures is the need to use the Range.EntireColumn property. Here's some code that groups, expands and collapses. I got this by googling and fooling around, but I think it gets the concepts right. Hopefully it's easy to translate into C++:
Sub test()
Dim ws As Excel.Worksheet
Set ws = ActiveSheet
With ws
If .Columns.OutlineLevel > 1 Then
'clear any existing hidden grouped columns and grouping
.Outline.ShowLevels columnlevels:=.Columns.OutlineLevel
.Range("1:1").EntireColumn.Ungroup
End If
'group
.Range("A:C").EntireColumn.Group
'collapse
ws.Outline.ShowLevels columnlevels:=1
'expand
ws.Outline.ShowLevels columnlevels:=.Columns.OutlineLevel
End With
End Sub