Google Sheets Addon or Formula that accomplishes the same thing as the Prevsheet Macro's for Excel - vba

I want to have a cumulative total running on each sheet (so the current total will be a value on the current sheet summed with the cumulative total from the previous sheet, each sheet representing a day of the month. In Excel this was definable in a Macro similar to this.
Function PrevSheet(rg As Range)
n = Application.Caller.Parent.Index
If n = 1 Then
PrevSheet = CVErr(xlErrRef)
ElseIf TypeName(Sheets(n - 1)) = "Chart" Then
PrevSheet = CVErr(xlErrNA)
Else
PrevSheet = Sheets(n - 1).Range(rg.Address).Value
End If
End Function
Is there anyway to do this in Google Sheets. It keeps referring back to sheet 1. Thanks
I left an editable link here which is a copy of what I am working on.
https://docs.google.com/spreadsheets/d/1cx9w9vOJXKj2WqYBoJOuZ7dWqP1VunFYpZbMLjdpkKQ/edit?usp=sharing

You can do that only using a script. Try this:
function PrevSheet(range) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var active = ss.getActiveSheet().getName();
for (i in sheets) {
if (sheets[i].getName() === active) {
return (sheets[i-1].getRange(range).getValues());
}
}
}
The only problem is, you will have to push the range as a String by surrounding it with quotation marks.
This will give you a range of Data
=PrevSheet("D2:D6")
This will give you the sum
=Sum(PrevSheet("D2:D6"))
UPDATE:
If you want this to be updated, use this script
function PrevSheetName() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var active = ss.getActiveSheet().getName();
for (i in sheets) {
if (sheets[i].getName() === active) {
return (sheets[i-1].getName());
}
}
}
And get the values like this:
=INDIRECT(PrevSheetName()&"!D2")
And
=SUM(INDIRECT(PrevSheetName()&"!D2:D6"))
Hope this helps.

Related

Apps script: Paste filtered range to the next empty row in specific column

I would like to create a code which copies a filtered column and pastes the whole column to the next available row in another sheet. The code below works however pastes the range in a loop until the end of the spreadsheet. How can I paste it just once?
I could not find an answer myself.
I would much appreciate your help!
function CopyFilter() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("MASTER");
var values = sheet.getDataRange().getValues();
Logger.log("VALUES "+values.length);
var criteria = SpreadsheetApp.newFilterCriteria()
.whenNumberGreaterThanOrEqualTo(1)
.build();
var range = sheet.getFilter()
.setColumnFilterCriteria(52, criteria)
.getRange();
range.getValues();
var sheet2 = ss.getSheetByName("DL CSV OUTPUT");
sheet.getRange("AZ4:AZ").copyTo(sheet2.getRange(2,41,sheet2.getLastRow()+1), {contentsOnly:true});
sheet.getFilter().remove();
}
Do not use the copy method. Simply select the range you are interested in, then get a range (of same size - very important) in the target sheet and set all values at once.
EXAMPLE:
const valuesToCopy = sheet.getRange("AZ4:AZ").getValues();
sheet2.getRange(2,3,valuesToCopy.length).setValues(valuesToCopy);
And no need to worry about: {contentsOnly:true}
Since the above method does not bring over any formatting.
Reference:
setValues(values)

In Google sheets, using a script, can I replace all the functions in cells with the plain text or number values they've calculated?

I have a spreadsheet with multiple sheets. The first sheet is an order form where you can enter customer details and their order summary.
On another sheet, these data are copied to relevant cells in a picking slip and a tax invoice, just using preformatted cells, and simple functions, ie:
='Order Submission Form'!E9
And then that cell is populated with the Customers name.
However, I then have a script which duplicates that spreadsheet, deletes all except the sheet with the picking slip and tax invoice, then turns it into a PDF. All of that code works fine, except that deleting all the redundant sheets also breaks the cell references, and so I end up with the picking slip and tax invoice just populated with #REF! in all the cells.
This is the complete code that I'm using to generate the PDF. I know I copied at least some of it from somewhere else, but I don't remember where I originally got it.
There is a section which seems to suggest it replaces the cell values with text to avoid broken references, but it does not seem to work, and it gives an error: "Incorrect Range height: Was 59 but should be 999 (Line 22, file createPDF)"
function checkSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = "Picking Slips";
var folderID = "1gp3dqdwMSXzwQ6gzhctbQk5ODnpBOHB_"; // Folder id to save in a folder.
var orderNumber = ss.getRange("'Picking Slips'!G4").getValue()
var pdfName = "Picking Slip # "+ orderNumber + " - " + Utilities.formatDate(new Date(), "GMT+8", "yyyy-MM-dd");
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var folder = DriveApp.getFolderById(folderID);
//Copy whole spreadsheet
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder))
//Dump the contents of the picking slip into order history
var destSheet = destSpreadsheet.getSheets()[0];
//repace cell values with text (to avoid broken references)
var sourceRange = sourceSheet.getRange(1,1,sourceSheet.getMaxRows(),sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
destRange.setValues(sourcevalues);
//delete redundant sheets
var sheets = destSpreadsheet.getSheets();
for (i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName){
destSpreadsheet.deleteSheet(sheets[i]);
}
}
//save to pdf
var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
var url = 'https://docs.google.com/spreadsheets/d/'+sourceSpreadsheet.getId()+'/export?exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
+ '&size=A4' // paper size legal / letter / A4
+ '&portrait=false' // orientation, false for landscape
+ '&fitw=true' // fit to page width, false for actual size
+ '&sheetnames=false&printtitle=false' // hide optional headers and footers
+ '&pagenumbers=false&gridlines=false' // hide page numbers and gridlines
+ '&fzr=false' // do not repeat row headers (frozen rows) on each page
+ '&gid='+sourceSheet.getSheetId(); // the sheet's Id
var newFile = folder.createFile(theBlob);
//Delete the temporary sheet
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
Any help would be greatly appreciated.
If you select the whole sheet and select copy and then paste special > paste values, only you will overwrite every formula in the sheet with its value.
You can script this as follows:
var range = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
range.copyTo(range, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);

Add cell one + cell two and reset cell two to zero

I hope my Intention is clear. It's for inventory management. The first cell Shows the current inventory and the second one is just a cell where you can type in your entries or outflow. I think the Code for Excel should be something like this, but I'm looking for the corresponding Google spreadsheet:
Sub LagerNeu()
Dim S As Integer
[F2].Select
S = ActiveCell.Value + ActiveCell.Offset(0, 1).Value
ActiveCell.Value = S
ActiveCell.Offset(0, 1).Value = 0
End Sub
Using the onEdit() method can watch for changes to the F column and update the cells as needed
Example:
function onEdit(e) {
var range = e.range; // e.g F2 is edited
// Only runs if the edit is in column F
if (range.getColumn() == 6) {
var old_value = range.offset(0, -1).getValue();
// Set the new value to the cell in the column to the left - E2
range.offset(0, -1).setValue(Number(old_value) + Number(e.value));
// Reset F2 to zero
range.setValue(0);
}
}

Get data from cells in a row and populate a new row in google sheets

I'm a total noob with scripts.
The idea is to get the data from the row of one sheet and then populate the row of the second sheet once a day.
I have 2 sheets with a spreadsheet.
1. A parent list of text in column 1 and numbers in column 2.
2. A target sheet to be populated.
From what I understand I have to do this
identify the parent sheet
identify the target sheet
set a variable (R) for the row of the parent sheet to get data from
find the data in column 1 of the parent sheet on row R
find the date in column 2 of the parent sheet on row R
Go to first empty row in the target sheet
Fill column 1 of the target sheet with data from column 1 of the parent sheet
repeat for column 2
update R to R+1 so when the function is triggered the next day then it gets the data from the next row.
I think that makes sense, but haven't got a clue of how to code that.
Would looooove the help of someone out there!
I manged to do steps 1 - 5 but stuck on one aspect.
Each day I want the script to go to the next row in the parent sheet.
I tried to set up a var currentRow for this, but when I put it within or out of the function it always goes back to 1.
var currentRow = 1;
function myFunction() {
// create a variable to know what row to get the data from in the parent list
Logger.log(currentRow);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var parent = ss.getSheetByName("parent");
var range = parent.getDataRange(),
values = range.getValues();
var row = values[currentRow],
text = row[0],
video = row[1];
Logger.log(text);
Logger.log(video);
currentRow = currentRow + 1;
}
Nice I managed to work out how to do it all.
I changed the currentRow to instead figure out what is the last row number in the target sheet.
Then the script adds 1 to that and get the data from the next row of the parent sheet.
This stuff is fun!
function myFunction() {
// create a variable to know what row to get the data from in the parent list
var ss = SpreadsheetApp.getActiveSpreadsheet();
var parent = ss.getSheetByName("parent");
var range = parent.getDataRange(),
values = range.getValues(),
lastRow = parent.getLastRow();
//get the position of the last row in the populate sheet
var populate = ss.getSheetByName("populate"),
range = parent.getDataRange(),
lastPopulateRow = populate.getLastRow();
var row = values[lastPopulateRow + 1],
text = row[0],
video = row[1];
Logger.log(text);
Logger.log(video);
Logger.log(lastRow);
Logger.log(lastPopulateRow);
//append to the populate sheet
populate.appendRow([text, video]);
}

Time and Date Apache Poi (if else statement not working)

I'm working in my DTR project using java and apche poi excel file. The if else statement below doesn't work. If time is less than 12 it must be in cell 1 and if not it must be in cell 3. But it does not do what it must do. If time is >= 12 it still in cell 1. Please help. Thank you.
Calendar calendar = new GregorianCalendar();
int month = calendar.get(Calendar.MONTH);
String IDnumF = (String) IDnum.getText();
FileInputStream file = new FileInputStream(new File("C:\\Database\\"+IDnumF+".xls"));
HSSFWorkbook wb = new HSSFWorkbook(file);;
Sheet sheet1 = wb.getSheetAt(month);
Cell cell = null;
Date date = new Date();
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
int day=dayOfMonth+7;
Row row = sheet1.getRow(day);
if(Calendar.HOUR_OF_DAY<12)//This code works
{
cell = row.createCell(1);
cell.setCellValue(""+ calendar.get(Calendar.HOUR_OF_DAY)+":"+calendar.get(Calendar.MINUTE));
}
else {//this part doesn't..
cell = row.createCell(3);
cell.setCellValue(""+ calendar.get(Calendar.HOUR_OF_DAY)+":"+calendar.get(Calendar.MINUTE));
}
Your problem is this line:
if(Calendar.HOUR_OF_DAY<12)
The value of Calendar.HOUR_OF_DAY (note the big C) is a constant, used when fetching the hour part of a calendar value
Based on the rest of your code, I think what you want is:
if (calendar.get(Calendar.HOUR_OF_DAY) <12)
That will fetch the hour of the day from your Calendar instance