I thought I figured out why my UDF is getting called twice and that it might also explain why the data values are different. There is a reference that could be termed circular. I got it to fail once, but now I cannot repeat it.
Here's a sample table. The application calculates a weighted rating for various products on several features. The UDF is passed 6 ranges. In this table, the calls are in cells D12-D14. The formulas are shown in I12-I14. The ranges defined as follows: Ratings (=Test!$D12:$H12), RtgsBest (=Test!$D$7:$H$7), RtgsWrst (=Test!$D$8:$H$8), RtgTypes (=Test!$D$9:$H$9), RtgReq (=Test!$D$10:$H$10), and RtgWts (=Test!$D$11:$H$11). All but Ratings are absolute in both the rows and columns. Ratings is absolute in the columns, but the rows adjust to match the calling cell row.
[TABLE="class: grid, width: 800"]
<tbody>[TR]
[TD="align: center"]R/C
[/TD]
[TD="align: center"]C[/TD]
[TD="align: center"]D[/TD]
[TD="align: center"]E[/TD]
[TD="align: center"]F[/TD]
[TD="align: center"]G[/TD]
[TD="align: center"]H[/TD]
[TD="align: center"]I
[/TD]
[/TR]
[TR]
[TD="align: center"]3[/TD]
[TD][/TD]
[TD="align: right"]Features[/TD]
[TD="align: center"]Price[/TD]
[TD="align: center"]Wt[/TD]
[TD="align: center"]Hgt[/TD]
[TD="align: center"]End[/TD]
[TD="align: center"]Comments
[/TD]
[/TR]
[TR]
[TD="align: center"]4[/TD]
[TD][/TD]
[TD="align: right"]Max Values[/TD]
[TD]$400[/TD]
[TD="align: center"]260[/TD]
[TD="align: center"]80[/TD]
[TD]End[/TD]
[TD]E4: =MAX(OFFSET(Header E:E,1,0):OFFSET(Footer E:E,-1,0))[/TD]
[/TR]
[TR]
[TD="align: center"]5[/TD]
[TD][/TD]
[TD="align: right"]Min Values[/TD]
[TD]$236[/TD]
[TD="align: center"]110[/TD]
[TD="align: center"]59[/TD]
[TD]End[/TD]
[TD]E5: =MIN(OFFSET(Header E:E,1,0):OFFSET(Footer E:E,-1,0))[/TD]
[/TR]
[TR]
[TD="align: center"]6[/TD]
[TD][/TD]
[TD="align: right"]Ave Values[/TD]
[TD]$295[/TD]
[TD="align: center"]167[/TD]
[TD="align: center"]67[/TD]
[TD]End[/TD]
[TD]E6: =AVERAGE(OFFSET(Header E:E,1,0):OFFSET(Footer E:E,-1,0))[/TD]
[/TR]
[TR]
[TD="align: center"]7[/TD]
[TD][/TD]
[TD="align: right"]Best Values[/TD]
[TD]$200[/TD]
[TD="align: center"]100[/TD]
[TD="align: center"]80[/TD]
[TD]End[/TD]
[TD]The best (top rated) values for each feature[/TD]
[/TR]
[TR]
[TD="align: center"]8
[/TD]
[TD][/TD]
[TD="align: right"]Worst Values[/TD]
[TD]$400[/TD]
[TD="align: center"]300[/TD]
[TD="align: center"]59[/TD]
[TD]End[/TD]
[TD]The worst (bottom rated) values for each feature[/TD]
[/TR]
[TR]
[TD="align: center"]9[/TD]
[TD][/TD]
[TD="align: right"]Scale Types[/TD]
[TD]Num[/TD]
[TD="align: center"]Num[/TD]
[TD="align: center"]Num[/TD]
[TD]End[/TD]
[TD]Specifies the type of feature
[/TD]
[/TR]
[TR]
[TD="align: center"]10[/TD]
[TD][/TD]
[TD="align: right"]Opt/Req Flags[/TD]
[TD]Opt[/TD]
[TD="align: center"]Req[/TD]
[TD="align: center"]Opt[/TD]
[TD]End[/TD]
[TD]Specifies if the feature is required or optional
[/TD]
[/TR]
[TR]
[TD="align: center"]11[/TD]
[TD][/TD]
[TD="align: right"]Weights[/TD]
[TD="align: center"]6[/TD]
[TD="align: center"]2[/TD]
[TD="align: center"]8[/TD]
[TD]End[/TD]
[TD]Specifies the relative weight for each feature
[/TD]
[/TR]
[TR]
[TD="align: center"]12[/TD]
[TD]Prod 1[/TD]
[TD="align: center"]45.89[/TD]
[TD]$250[/TD]
[TD="align: center"]130[/TD]
[TD="align: center"]62[/TD]
[TD]End[/TD]
[TD]D12: =wtdrtg(Ratings,RtgsBest,RtgsWrst,RtgTypes,RtgReq,RtgWts)[/TD]
[/TR]
[TR]
[TD="align: center"]13[/TD]
[TD]Prod 2[/TD]
[TD="align: center"]42.63[/TD]
[TD]$236[/TD]
[TD="align: center"]110[/TD]
[TD="align: center"]59[/TD]
[TD]End[/TD]
[TD]D13: =wtdrtg(Ratings,RtgsBest,RtgsWrst,RtgTypes,RtgReq,RtgWts)[/TD]
[/TR]
[TR]
[TD="align: center"]14[/TD]
[TD]Prod 3[/TD]
[TD="align: center"]52.50[/TD]
[TD]$400[/TD]
[TD="align: center"]260[/TD]
[TD="align: center"]80[/TD]
[TD]End[/TD]
[TD]D14: =wtdrtg(Ratings,RtgsBest,RtgsWrst,RtgTypes,RtgReq,RtgWts)[/TD]
[/TR]
[TR]
[TD="align: center"]15
[/TD]
[TD="align: center"]Ftr[/TD]
[TD="align: center"]Ftr[/TD]
[TD="align: center"]Ftr[/TD]
[TD="align: center"]Ftr[/TD]
[TD="align: center"]Ftr[/TD]
[TD="align: center"]Ftr[/TD]
[TD][/TD]
[/TR]
</tbody>[/TABLE]
The data columns are E:G. In this example there are just 3 features to be rated, Price, Wt, & Hgt. But the ranges include columns D & H, the column just before the first data column and the one just after the last data column. This allows me to add columns without having to redefine the ranges. They dynamically redefine themselves. So the UDF has to start indexing at "2" and stop at N-1, where N is the number of columns in the extended ranges.
The table as shown above works without any problems. The UDF is not called twice from each cell and all of the values match.
The problem arises when I change the contents of any of the Best or Worst cells from a literal value to a formula. Consider E7. This is the best (highest rated) value for the Price feature. Products that cost $200 or less will get the highest rating. Products that cost $400 or more will get the lowest rating. Products that cost somewhere in between will get a prorated rating.
As long as these are literal values, everything is fine.
Now consider rows 4 & 5. Row 4, as can be seen from the formula I4-I5, is the maximum value for all of the products. Similarly, row 5 in the minimum. Header is defined as "=Test!$11:$11" and Footer as "=Test!$15:$15". These serve the same purpose of allowing me to add products without having to adjust the formulas for max, min, and average. The maximum of $250, $236, & 400 is $400 and the minimum in $236.
Now suppose I want to dynamically adjust the Best/Worst values to be the same as the Max/Min values (or the Min/Max values if lower is better than higher, as in this case with Price). If I add a new product that costs more than $400 or less than $200, I want the ranges to automatically adjust. I could replace the $200 in E7 with "=MinValue", where MinValue is defined as "=Test!$5:$5". The first time I did that, the UDF was called 4 times. I believe the first time the value the UDF saw for E7 was empty or null. The next three times, it was not. I say "I believe", because I didn't pay close attention thinking I could reproduce the condition. But now I have changed to a literal and back to an expression ad I can't get it to fail.
My theory was that since MinValue based on all of the ratings but the one associated with the calling cell was also passed as part of the Ratings range, it resulted in a circular reference. But now that is not happening.
I've had enough for tonight. I'm going to bed. I'll try again in the morning.