Is there a way to autofill Pi DataLink data using VBA? - excel

I am pulling hourly data out of a server in Osisoft Pi Historian for thousands of distinct data points. The sampling function in question is PISampDat
When I try to copy one row to the next in an effort to save time and effort, I get a message to "Resize to show all values". But this message never updates to actual values when I tell the program to recalculate.
I am left with two options: A) MANUALLY enter the formula parameters for each row, a daunting and torturous task, or B) one of you can mercifully tell me how I can use VBA to autofill all of these rows.
The formula in Cell H280 is the following:
=PISampDat(Sheet1!$T$3,"2019-05-01","2019-06-01","1h",2,Sheet3!$B$280)
This is replicated in all cells up through ABX280 (values for each hour in the month of May, and including midnight of June 1, 2019.)
I don't know where to start in VBA.
I have tried getting rid of the $ before the 280, but then I am prompted "You are not allowed to change part of an array."
Attempts to copy the formula into other lines results in the message "Resize to show all values", but resizing and recalculating does nothing. Either that, or I'm just copying the values from other lines and the formula isn't actually getting called for other data items.

I don't think you need VBA to achieve this. PISampDat uses an array formula so you can either refresh it by using Ctrl+Shift+Enter or by re-opening the function wizard to re-enter a bigger range for the parameter locations.
To go further I'd suggest to use the following resource: Creating Basic Reports with PI Datalink

Related

How to identify and name different ranges in one column in Excel?

I have a recorded drive cycle of a truck which includes speed and coordinates over time. The file looks like this (simplified version)
I want to know the number of times the truck is stopped (when speed = 0) and number them. Therefore, I would like to group the intervals with '0' values (vehicle stopped) in the Speed column and name them in order (Stop 1, Stop 2, etc). Ultimately, my goal would be to somehow be able to calculate the number of stops and duration like this:
Is there any function in Excel which would allow me to do something like that? Thank you.
You can do it using Pivot Tables and a helper column. Also if you have Excel365 with functions like FILTER,UNIQUE and SUMIFS
Formula helper column is just to enumerate properly each group of stops. Notice data need to be sorted properly as your exampel or it won't work:
=IF(D2="STOP";IF(D1="STOP";E1;MAX($E$1:E1)+1);"")
Then pivot table can be inserted:
Helper Column and Vehicle Stop into rows section
Time-step seconds into values section, formated as Time and operation=Sum
Filter field Helper Column to exclude blanks
If you have Excel 365, you can get this output with advanced formulas. In cell J14 formula is:
=UNIQUE(FILTER(D2:D19&E2:E19;D2:D19="STOP"))
And K14 is (and drag down) is:
=SUMIFS($B$2:$B$19;$D$2:$D$19;"STOP";$E$2:$E$19;MID(J14;5;99))
Anyways, I've uploaded the workbook to Gdrive so you can see the Pivot Table and the formulas by yourself. If you don't jave Excel 365, the formulation part may give some errors when you open it:
https://docs.google.com/spreadsheets/d/1t1INxGKJRHFexWnSC5LlIi37JrThjajs/edit?usp=sharing&ouid=114417674018837700466&rtpof=true&sd=true
Just as a postscript to this, you could do the same thing without using helper columns by comparing offset ranges to see where the transitions in speed occurred from 0 to 10 (go) or 10 to 0 (stop). The problem is that normally you would have to go outside the data range (a2:a16 and c2:c16) which gets you either a header cell (a1 or c1) or a blank cell (a17 or c17). In the case of time, there is also a special case where the first time-step is taken to be zero.
All this can be avoided in Excel 365 by using vstack to add appropriate dummy values to the beginning or end of the two ranges:
=LET(timeRange,A2:A16,
speedRange,C2:C16,
timeRange1,VSTACK(A2,timeRange),
speedRange1,VSTACK(1,speedRange),
speedRange2,VSTACK(speedRange,1),
startTime,FILTER(timeRange1,(speedRange1>0)*(speedRange2=0)),
endTime,FILTER(timeRange1,(speedRange1=0)*(speedRange2>0)),
stopTime,endTime-startTime,
label,"STOP "&SEQUENCE(ROWS(stopTime)),
HSTACK(label,stopTime))

How to insert a formula by macro?

The issue has been solved.
It would appear that when I made some changes to capture data a little while ago, I inadvertently broke the order of things. When the above bit of code was running, the [Date Out:] column was indeed empty, so Excel was reporting properly.
I've since reordered the input of formulas and now the sheet works correctly, with credit to #BigBen and #Michael Wycisk.
I created an Excel sheet to draw together the data from several other Excel sheets into one to keep track of a project.
I have a formula that works if it is written into a range of cells with the source data sheet open in the background. If I ask a macro to put it into the required cells as the main sheet opens then the formula fails. By 'fail', I mean the formula checks it's first column to see if data is present or not and then decides that the column is empty regardless, therefore falsely reporting 'nothing sent' if there is a date in the "Date Out" column.
Here is the line in question.
WSR.Range("ReportTable[Latest Portare Instance:]") = "=IFERROR(IF([Date out:]="""",""Nothing Sent"",IF(AND([Received by Serial:]="""",[Received by Asset:]=""""),""Not Received"",IF([Received by Asset:]<>"""",LOOKUP(2,1/('Stock Movement Archive Defra.xlsx'!Archive[Asset No:]=$J2),'Stock Movement Archive Defra.xlsx'!Archive[Location:]),LOOKUP(2,1/('Stock Movement Archive Defra.xlsx'!Archive[S/No:]=$I2),'Stock Movement Archive Defra.xlsx'!Archive[Location:])))),""Issue"")"
It's one of several formulas, all inserted the same way and the rest work. As far as I can tell the formula is being inserted correctly, just that this one stops at the first if statement.
For reference, I have tried changing the first 'if' statement to start IF([Date out:]<>"""", the formula then either states "Nothing Received" where there is no date or pulls the correct data if there is a date. Also tried changing the format of the "Date Out" column.
The formula looks fine for me. The only problem might be that you need to use the .Formula property after the Range object:
WSR.Range("ReportTable[Latest Portare Instance:]").Formula = "=IFERROR(IF([Date out:]="""",""Nothing Sent"",IF(AND([Received by Serial:]="""",[Received by Asset:]=""""),""Not Received"",IF([Received by Asset:]<>"""",LOOKUP(2,1/('Stock Movement Archive Defra.xlsx'!Archive[Asset No:]=$J2),'Stock Movement Archive Defra.xlsx'!Archive[Location:]),LOOKUP(2,1/('Stock Movement Archive Defra.xlsx'!Archive[S/No:]=$I2),'Stock Movement Archive Defra.xlsx'!Archive[Location:])))),""Issue"")"
To make sure that your formula is correct (you say it works fine when typed into the cell), you might type it into the cell, select the cell and then type ?ActiveCell.Formula into the Immediate Window inside the VBE (don't forget to check that the quotation marks are correct).

Excel Formula with OFFSET Fails When Copied to Different Sheet

I've been struggling with this longer than I care to admit, but I have a fairly simple OFFSET function call which works on one sheet, but if I copy it to a different sheet it gives a #VALUE error.
On a sheet named "Deliverable" I have this formula in a cell:
=OFFSET(Deliverable!$B$72,1,0,,3)
and it works fine.
If I go to any other sheet and use the same exact formula, or use it in the Name Manager, it gives a #VALUE error.
If I leave off the final parameter indicated the number of columns I want, it does work:
=OFFSET(Deliverable!$B$72,1,0)
but of course isn't giving me the range I need.
Any idea what's going on with this?
I'm using Excel 2016 on Windows 7.
-- Updated Info --
In a nutshell, my spreadsheet has two cells which I'm using as dropdown lists, where the 2nd cell's list feeds off the selection in the first. The data they are based on has this format:
OptionA A B C D
OptionB A B
OptionC D E F
So the first dropdown uses a simple Data Validation source pointing to the column with OptionA, OptionB, etc. Once that's chosen, the second dropdown list should contain the appropriate options for the one selected. So if OptionB is selected, then the 2nd dropdown list should show A and B.
When I initially wrote this, the data validation source was just a simple VLOOKUP entry, but the lists often had blanks since the number of options varies for each entry. Wanting to fix it up a bit, I ended up with this formula:
=OFFSET(Deliverable!B72,Deliverable!B87,0,1,COUNTA(OFFSET(Deliverable!B72,Deliverable!B87,0,1,5)))
There won't be any more than 5 options, and there are no empty cells in the middle of the data to filter out.
In one spreadsheet I have I used this as a named range definition, then specified the named range for the cells data validation source and it worked. In this other spreadsheet however, it gave me the error described earlier.
However, it looks like when I enter the statement directly into the data validation source field and not in the name manager, it works as expected.
Am I taking the totally wrong approach?
What is it that you want this formula to do? As written, it is returning a block of three horizontal cells. The #VALUE error is Excel's way of telling you "Hey, you're trying to return three cells, but I can't fit them all in the one cell that you are calling this formula from".
The reason you see a result in some places and not others is because of something called Implicit Intersection. Give it a spin on Google. But basically, it just returns whichever one of those three results corresponds to the column that the formula is entered into. If you copy that exact same formula to say row F you will see that it returns a #VALUE error there, because it doesn't know what cell it should return given the column you're calling it from doesn't match any of the cells it is returning. The fact that you don't know this indicates that the formula you're using doesn't in fact do what you think it does.
--UPDATE --
Okay, following your further clarificaiton it seems that you're talking about Cascading Dropdowns aka Dynamic Dropdowns. Lots of info on Google about how to set these up, but you may be interested in an approach I blogged about sometime back that not only provides this functionality, but also ensures that someone can't later on go and change the 'upstream' dropdown without first clearing the 'downstream' one should they want to make a change.
Note that those links talk about a slightly complicated method compared to others, but the method has it's advantages in that it also handles more levels than two, and your DV lists are easily maintained as they live in an Excel Table.
This sounds like an array equation. Try hitting Ctrl+Shift+Enter in the other sheets to validate it as an array equation.
Whenever you need to reference ranges instead of single cells, Excel needs to know that you are working with arrays.

(MS EXCEL) How do I replace cells with formulas to its calculated value AUTOMATICALLY?

I am making a payroll program in Excel and one of my concerns is that the salaries of the employees are searched using the INDEX and MATCH or VLOOKUP function. The problem is if the salaries get updated in the future (e.g. a raise or changes in rates), all the previous entries that used the old salaries will be updated to the new salaries. This is a disaster and would make my entire program useless and inefficient. Therefore I need to automatically lock previous calculated cells after a certain time.
Edit: Note we do not want to do this manually such as copy pasting values only because almost all cells are connected to each other and one mistake by the encoder or if they forget to do this before updating a value, everything will be messed up.
No! Not copying and pasting, there's a simpler way. You want to convert the Formula property of a given cell (what's shown in the formula bar in Excel) into the Value property of the cell (what's shown in the cell on the spreadsheet). For a given range A1:B6 this would done by the statement
Range("A1:B6").formula = Range("A1:B6").value
But there's a quirk in Excel that you can run faster by accessing a Value2 property, so
Range("A1:B6").formula = Range("A1:B6").value2
The rest of the code is left as an exercise for the reader :-)

Excel errors vanish when I manualy enter formula

SO I'm trying to build a growth at a reasonable price screener, given a list of all stocks on the NYSE, that reads in and fills my column A with the ticker and B with the company name. The next columns use the SMF add-in from Yahoo and pulls data, such as the P/E and other metrics, off GARP (GROWTH at Reasonable price.) The formulas were built in the first row and dragged down over the rows of stocks. The issue that I am having is the formulas preform their job for the fist hundred or so stocks (rows), and then they all return error. However, if I scroll to a Blue chip stock and, in the formula box, click and press enter, the desired value will replace the error result.
Online I have found forms that suggest using arrays yet I cant seem to get an array to work, assuming my syntax would be =smfGetElementNumber(A4:A3298,#), where 'number' references a predefined function in the smf plugin and the data range is the spread of stock tickers.
Please advise as to why I receive this issue and what I can do to fix it.
Couple things you can try:
Make sure , Formulas->Calculation Options->Automatic is checked
Check the references of the cells in your formula i.e Relative vs Absolute referencing
Edit:
If You have Calculation Options set to Manual and update the dependent cells follow this hack
Select the cells that have issues and Select Data->Text to Columns->Finish

Resources