The problem is the LOOKUP(...) part of the function. If you use the Evaluate Formula tool, you will see that 1/(D8:D131<>"") part of the formula returns an array of 1s interspersed with #Div/0 errors. From the help file for the LOOKUP() function:
Quote Originally Posted by MS Excel help
Important: The values in lookup_vector must be placed in ascending order: ..., -2, -1, 0, 1, 2, ..., A-Z, FALSE, TRUE; otherwise, LOOKUP might not return the correct value.
An array of 1s interspersed with #Div/0 errors is not sorted, so the lookup results are unstable and erratic. This strategy works well when your "filled range" is a contiguous block of cells followed by a contiguous block of empty cells, but your table is not set up that way. Because your table is setup with blanks interspersed with two different types of values (raw data and percentage change calculations), this "last value lookup" needs to be more complex.

Solutions will probably vary. Before exploring solutions, are you absolutely required to program the spreadsheet in this arrangement? I have found over the years that, if I pay attention to how I arrange my data/calculations in the spreadsheet, programming the sheet can be a lot easier. In this case, thinking long term, you will find it easier to program if you store the raw data in a nice database arrangement, then you can fill in this spreadsheet using lookups, queries, and other functions and tools that are designed to work on a good database. Are you willing to consider a more complete re-write of the spreadsheet?

If you decide that you must use the spreadsheet exactly as is, then the solutions will involve re-writing the LOOKUP() part of the function in a way that more reliably identifies where the "last value (but not really THE last value)" is in the column.