Manipulate HTML Table in Browser - javascript

I do a lot of reading of charts and graphs, and I was wondering if there was a FF or GC extension that allows me to do things like swap rows and columns in a drag and drop type fashion.
For example, if I want to compare the values in Rows 1, 55, 92 and 143, is there a way I can rearrange the table to put those four rows at the top of the chart for easy comparison?
I know I could probably copy and paste it into Excel, I was hoping that there was a solution with the browser.

Firefox:
https://addons.mozilla.org/en-us/firefox/addon/tabletools2/
https://addons.mozilla.org/en-us/firefox/addon/export-to-csv/
You can also export to excel:
How to export html table to excel using javascript
http://www.mrkent.com/tools/converter/
I however... highlight what I need > cntrl c > cntrl v into excel and done.

var rowIndexWanted = [4, 5];
var table1 = document.getElementById('table1');
var table1body = table1.getElementsByTagName('tbody');
var rows = table1.getElementsByTagName('tr');
var rowsWanted = [];
for(i in rowIndexWanted)
{
rowsWanted.push(rows[rowIndexWanted[i]]);
}
for(i in rowsWanted)
{
table1body[0].insertBefore(rowsWanted[i], table1body[0].childNodes[0]);
}

Tip: you can select cells (in Firefox at least) by maintaining the Ctrl key pressed and selecting range of cells.
Bookmarklets from J. Ruderman let you sort a table by any column, transpose it or number the rows.
What you're searching seems similar to functionalities offered by frameworks like Kendo: column reordering or Aggregates?

Related

How to Merge rows in Google Sheets

I tried digging this stuff and have no solution so I'm hoping someone can assist. I have a sheet with the following:
Data
123|456|789
111|222|333
etc...
Result Needed
|123 456 789|
|111 222 333|
etc...
I'm trying to avoid formulas (=Concat) and (=A2&" "&B2&" "&C2) etc...
I tried sheet.getRange(2,1,1,2).mergeAcross(); and it merged the cells and kept he left-most value. Google searches point to the formula solution.
You can try Array.join() for each row:
Snippet:
var jointRowsArray = sheet
.getRange(2, 1, 2, 3) //A2:C4
.getValues()
.map(function(row) {
return [row.join(' ')];//join Each row
});
sheet.getRange(2, 4, jointRowsArray.length, 1).setValues(jointRowsArray);
To Read:
Arrays
Array#join
Array#map
Range#setValues
Best Practices
var range = sheet.getRange(2,1,1,2)
var values = range.getValues()
range.clearContent()
sheet.getRange(2,1).setValue(values.join(' '));
You can pull the values into JS and then join and insert them into a single cell. You can also place this inside an iterator and do something akin to getRange(i,1,1,2). This can be triggered manually or by an edit hook.
However, this seems like the perfect fit for a single formula.
=TRANSPOSE(QUERY(TRANSPOSE(A:C),,COLUMNS(A:C)))
The formula would go on the first row in perhaps column D. JOIN functions cannot usually be arrayed in google sheets, and you would normally have to put a formula in for every row. However, here we are tricking the sheet into thinking our data is the header and displaying it accordingly.

Google apps script getRange() range not found error

I feel like I'm going about this in all the wrong way. I'm trying to automate some of my workload here. I'm cleaning up spreadsheets with 4 columns (A-E), 2000+ rows. Column B contains website URLs, column D contains the URL's business name, generated from another source.
Sometimes the tool doesn't grab the name correctly or the name is missing, so it populates the missing entries in column D with "------" (6 hyphens). I've been trying to make a function that takes an input cell, checks if the contents of the cell are "------", and if it is the function changes the contents of the input cell to the contents of the cell two columns to the left (which is generally a website url). This is what I've come up with.
function replaceMissing(input) {
var sheet = SpreadsheetApp.getActiveSheet();
//sets active range to the input cell
var cell = sheet.getRange('"' + input + '"');
//gets cell to fill input cell
var urlCell = sheet.getRange(cell.getRow(), cell.getColumn() - 2);
//gets contents of input cell as String
var data = cell.getValue();
//gets contents of urlCell as String
var data2 = cell.getValue();
//checks if input cell should be replaced
if (data === "------") {
//set current cell's value to the value of the cell 2 columns to the left
cell.setValue(data2);
}
}
When I attempt to use my function in my sheet, the cell is returning the error
Error Range not found (line 4).
I'm assuming, based on similar questions people have asked, that this is how you use the A1 notation of the function with an argument. However, that doesn't seem to be the case, so I'm stuck. I also don't think my solution is very good period.
1) It's somewhat ambiguous in GAS documentation, but custom functions have quite a few limitations. They are better suited for scenarios where you need to perform a simple calculation and return a string or a number type value to the cell. While custom functions can call some GAS services, this practice is strongly discouraged by Google.
If you check the docs for the list of supported services, you'll notice that they support only some 'get' methods for Spreadsheet service, but not 'set' methods https://developers.google.com/apps-script/guides/sheets/functions
That means you can't call cell.setValue() in the context of a custom function. It makes sense if you think about it - your spreadsheet can contain 1000s of rows, each with its own custom function making multiple calls to the server. In JavaScript, every function call creates its own execution context, so things could get ugly very quickly.
2) For better performance, use batch operations and don't alternate between read / write actions. Instead, read all the data you need for processing into variables and leave the spreadsheet alone. After processing your data, perform a single write action to update values in the target range. There's no need to go cell by cell when you can get the entire range using GAS.
Google Apps Script - best practices
https://developers.google.com/apps-script/guides/support/best-practices
Below is a quick code example that runs onOpen and onEdit. If you need more flexibility in terms of when to run the script, look into dynamically-created triggers https://developers.google.com/apps-script/reference/script/script-app
Because your spreadsheets have lots of rows, you may hit the execution quota anyway - by using triggers you can work around the limitation.
Finally, if a cell containing '----' is a rare occurrence, it might be better to create another array variable with new values and row numbers to update than updating the entire range.
Personally, I think the single range update action would still be quicker, but you could try both approaches and see which one works best.
function onOpen(){
test();
}
function onEdit() {
test();
}
function test() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('yourSheetName');
//range to replace values in
var range = sheet.getRange(2, 4, sheet.getLastRow() - 1, 1);
//range to get new values from
var lookupRange = range.offset(0, -2);
//2d array of values from the target range
var values = range.getValues();
//2d array of values from the source range
var lookupValues = lookupRange.getValues();
//looping through the values array and checking if array element meets our condition
for (var i=0; i < values.length; i++) {
values[i][0] = (values[i][0] == '------') ? lookupValues[i][0] : values[i][0];
}
// one method call to update the range
range.setValues(values);
}

Individual column filtering with Handsontable?

What I'm looking for is an individual column searching function (exactly as this datatables spreadsheet example) for the Handsontable spreadsheet plugin.
What's already existing and has been developed by the Handsontable team is :
Multiple filtering Excel-like (but included in the PRO version) - Cons for my case are that it's not free, and it doesn't quite fit well what I'm looking for.
Highlighting the cell(s) or row(s) based on an user input - The Con is that I need to only display the relevant row(s)
Is there such thing as displaying only the relevant row(s) based on multiple inputs from an user with Handsontable ?
Based on the solution of this blog, I managed to code a solution.
See this JS fiddle that answers all my requirements.
The main function I was looking for is this one :
// The function push every row satisfying all the input values into an array that is loaded
function filter() {
var row, r_len, col, c_len;
var data = myData; // Keeping the integrity of the original data
var array = [];
var match = true;
for (row = 0, r_len = data.length; row < r_len; row++) {
for(col = 0, c_len = searchFields.length; col < c_len; col++) {
if(('' + data[row][col]).toLowerCase().indexOf(searchFields[col]) > -1);
else match=false;
}
if(match) array.push(data[row]);
match = true;
}
hot.loadData(array);
}
What I did is keeping synchronized a table of Strings with the input fields (searchFields), compare the data of each row between inputs and their corresponding column, and push into an array the relevant row(s) to finally display the resulting array. This function is called for any change in the input fields which result in a live table filtering.
Note that I tried my solution for ~10k rows and their isn't any performance issue with Chrome, Firefox and IE.
Also note that I managed to find a solution to keep synchronized the current displayed table with the original data when editing the values, but this is IMO out of the scope of this question. Please let me know in the comment if you're interested about this.

jQuery DataTables 1.10: Which column is it sorted on right now?

Using DataTables 1.10,
I have a DataTable with a default sort and the user can resort by some of the other columns.
How do I detect the column by which the table is currently sorted?
Some context which may not be relevant to answering the question: What I'm really trying to do is "export" the table to a non-interactive HTML table. This DataTable is generated programmatically and then turned into a DataTable, so after some searching for export options it looks like it will be easier to essentially regenerate the original table than to actually export. But I need the regenerated table to have the rows in the same order as the current sort.
The current sort state sortInfo can be retrieved like this:
var apiObject = $("#myPlainTable).DataTable( dtOptions );
// ...
var sortInfo = apiObject.settings().order()
More specifically, the column and direction are encoded like this:
var sortCol = sortInfo[0][0]; // counting from left, starting with 0
var sortDir = sortInfo[0][1]; // either "asc" or "desc"
Caveats:
The sortInfo object will have the above format after the user changes the sorting; if you specify the initial sort by setting dtOptions.order using a different format, then the sortInfo object will have the original value you specified until the user changes the sorting. (For example, DataTables will accept [1,'asc'] in addition to the above [[1,'asc']]; I didn't test what happens if you pass a value DataTables can't use.)
This describes the default case where you sort by one column only, not using the multi-column sort feature.
When you are using dataTables 1.10.x already, why not use the API? By that it is easy :
table.rows().data()
returns an array of arrays containing the current content of the table, i.e the rows as they are currently sorted. So if you want to export or clone the content of a dataTable to a static table, you can actually do it very simple :
$("#clone").click(function() {
var cloneTable = '';
table.rows().data().each(function(row) {
cloneTable += '<tr><td>' + row.join('</td><td>') + '</td></tr>';
})
$('#cloneTable tbody').html(cloneTable);
})
demo -> http://jsfiddle.net/zuxm2e68/
If sending to the server you check the
order[i][column]
order[i][dir]
for column and direction. See here
Since you are using 1.10, you can use the following:
var table = $('.myTable').dataTable({ /* Your options */ });
var sortArray = table.api().settings().aaSorting; // gives array
If you are using API already via $('.myTable').DataTable({...}), you can omit the .api().

Create Excel Format Output using HTML and JavaScript

I had interview and question asked was:
Write a JS plugin that can take cell and value as input and render excel format output on browser. For example,
Given Input (cell and value):
J3 = 5
A2 = 20
K1 = 10
Output on browser should be in excel format
A B C ....... J K .......
1 10
2 20
3 5
..
I Was looking for correct solution for the problem.
I tried solving this problem (writing psudeo code)
var cell = {"J3": 5, "A2":20, "K1": 10}
// Function they will call for generate excel style table
generateExcel(cell, selector) {
1. create blank table which has A-Z column (with selector as A-Z resp) and 1 to 100 rows (with selector as 1 to 100 resp)
2. Loop through each cell and for each cell
2.1 find the column (J) and row (3)
2.2 Add/replace value in that TD
3. Once all the information from cell in enter in table, print the table in the document at given selector
}
They said it won't be efficient for huge number of cell inputs. I suggest that we can use Matrix create table
A B... J K ....
1 [ 10 ]
2 20
3 5
I think you started off well. Begin by creating a table that will contain the elements. This will be 26 columns wide and as tall as the largest y value. Convert the letters to numbers.
Sorry for w3schools link, I'm liable to get downvoted for even mentioning them, but they have the best laid out documentation on the table object that I could google for you. I will update it if someone has something better.
http://www.w3schools.com/jsref/dom_obj_table.asp
MDN Tutorial
https://developer.mozilla.org/en/Traversing_an_HTML_table_with_JavaScript_and_DOM_Interfaces
You can then access the table cell most efficiently through
var table = ;//get by id or create element, not sure what they expect
table.rows[y].cells[x].appendChild(...);
Excel spreadsheets are tables. Can you use a simple table? If so, I would recommend the CSS border-collapse property to make it look better, as well as perhaps reducing cell padding and margin.

Categories