NPOI Formula evaluation error IndexOutOfRangeException - excel-formula

I have an Excel.xls. There are many cells with complex formulas. When I got the results of several formulas, an exception occurred.
var a = wk.GetCreationHelper().CreateFormulaEvaluator();
a.ClearAllCachedResultValues();
var cellv = a.EvaluateInCell(cell);
The evaluation function EvaluateInCell returned IndexOutOfRangeException: Index was outside the bounds of the array.
It is worth noting that the formula in this cell is very long and has multiple levels of nesting.
Its formula is this:=IF(SUM(D22:D10000)+SUM(M28:M193)+SUM(M22:M23)+SUM(D22:D10000)+SUM(E22:E10000)*1.2=0,"",SUM(D22:D10000)+SUM(M28:M193)+SUM(M22:M23)+SUM(E22:E10000)*1.2)
First of all, I don't think it is a problem with the formula, because Excel can calculate the result by itself, but it returns an error through Npoi.
I looked through the source code and found that the error may be caused by a negative number in getHashCode. This is my guess, but I still don't know how to solve this problem. The source code is as follows
int startIx = cce.GetHashCode() % arr.Length;
for (int i = startIx; i < arr.Length; i++)
{
CellCacheEntry item = arr[i];
if (item == cce)
{
// already present
return false;
}
if (item == null)
{
arr[i] = cce;
return true;
}
}
for (int i = 0; i < startIx; i++)
{
CellCacheEntry item = arr[i];
if (item == cce)
{
// already present
return false;
}
if (item == null)
{
arr[i] = cce;
return true;
}
}

Related

Check50 Errros: Not passing " handles most basic words properly" and "handles substrings properly" tests. Check50 also can't check for a memory error

I am working on Pset5 Speller. I've managed to get all my errors down to three, but I cannot figure out how to fix my program so that it handles most basic words and handles substrings. I have run debugger, but it doesn't really help. I have also run valgrind and it says that no memory leaks are possible. I think the problem maybe my check function or hash function, so I have changed them a few times but I still get the same check50 results. The sumbit50 link:
https://submit.cs50.io/check50/57b8af186bcdadea0b585f0785ef47a5cf317b99 says that check50 only ever finds 1 word in the dictionary and identifies all words as misspelled. I really am not quite sure what the problem is. Can someone help me please? Here are my checks and hash functions. Thank you!!!
// Hashes word to a number
unsigned int hash(const char *word)
{
// hash function created by Deliberate Think on Youtube
int hash_key = 0;
int n;
for (int i = 0; word[i] != '\0'; i++)
{
if (isalpha(word[i]))
{
n = word[i] - 'a' + 1;
}
else
{
n = 27;
}
hash_key = ((hash_key << 3) + n) % N;
}
return hash_key;
}
// Returns true if word is in dictionary else false
bool check(const char *word)
{
// create an array to store words, then copy words from table to compare
int n = strlen(word);
char wordcheck[LENGTH + 1];
strcpy(wordcheck, word);
for (int i = 0; i < n; i++)
{
wordcheck[i] = tolower(word[i]);
}
//hashes word, then accesses linked list at that value
int j = hash(wordcheck);
node *cursor = hashtable[j];
if (hashtable[j] != NULL)
{
//iterates through linked list: cursor pointer starts at head of list and while there is a value, it moves on to the next word in the list
while (cursor != NULL)
{
//if the word is found, return true
if (strcmp(cursor->word, wordcheck) == 0)
{
return true;
}
else
{
cursor = cursor->next;
}
}
}
return false;
}
bool load(const char *dictionary)
{
//opens dictionary file
FILE *inputfile = fopen(dictionary, "r");
if (inputfile == NULL)
{
return false;
}
//initializes new node pointer and reads words from new file while !EOF
char word[LENGTH + 1];
while (fscanf(inputfile, "%s", word) != EOF)
{
//actually creates and initializes new node( creates space in memory for node using malloc function) and copies word into node while keeping tracking of # of words
node *new_node = malloc(sizeof(node));
if (new_node == NULL)
{
unload();
return false;
}
else
{
strcpy(new_node->word, word);
}
//hashes words in node to determine which linked list to use
int j = hash(new_node->word);
//initializes node pointer to first bucket in hashtable
node *head = hashtable[j];
if (head == NULL)
{
//if there is no data in linked list, new_node becomes head of linked list
hashtable[j] = new_node;
}
else
{
//if data exists, node points to next word in list, then head of linked list points to node pointer
new_node->next = hashtable[j];
hashtable[j] = new_node;
}
wordcount++;
fclose(inputfile);
}
return true;
}
I solved it! I had to change the way the hash function was written inside of the load function and rewrite fclose(inputfile) to be outside of one of the curly braces. All errors gone!

Google Sheet custom function not returning string

I am new to Google Sheet scripting.
I am writing a code to strip the sixth components from a long text that is based on a naming convention. The text have 6 parts all separated by an underscore. However, my code is not returning anything
function RetailerStrip(account) {
var count = 0;
var retname = "";
var retcount = 0;
for(var i = 0, len = account.length; i < len; i++) {
if (account[i] =="_") {
++count;
}
if (count == 5) {
retname[retcount]= account[i];
++retcount;
}
}
return retname;
}
I then call this function from sheet as below
=RetailerStrip("abc_def_ghi_jkl_mno_pqr")
When I tried to declare 'retname' as an array the function did return the required text (fifth component) but the text was spread across multiple cells with on character in each cell, and not as a single string in one cell
var retname = [];
Please help
You could try this:
function RetailerStrip(str) { return str.split('_')[5]; }
The split() method creates an array.
But if you prefer to stick with the string-iteration method, you could use this:
function RetailerStrip(account) {
var count = 0;
var retname = []; // Array
var retcount = 0;
for (var i = 0, len = account.length; i < len; i++) {
if (account[i] =="_") {
++count;
}
if (count == 4) {
retname[retcount]= account[i];
++retcount;
}
}
retname.shift(); // To get rid of the underscore from the array
var retnameString = retname.join(''); // To convert the array to a string
return retnameString;
}

Why is the rcpp function slow?

I have made a simple function that sets a column reversal_indicator to "yes" if a value in the Reversal_Accounting_Transaction_ID is present anywhere in the column Accounting_Transaction_ID (i.e in other rows).Most entries in the Reversal_Accounting_Transaction_ID column are likely to be blank and therefore should be "no".
The dataframe is created from a 6gb csv file (assume approx 6 million rows) and is being processed on databricks.
I am not really sure why its taking such a long time
Rcpp::cppFunction('
std::vector<std::string>
reversals(DataFrame frame)
{
std::vector<std::string> Accounting_Transaction_ID = as<std::vector<std::string> >(frame["BELNR"]);
std::vector<std::string> Reversal_Accounting_Transaction_ID = as<std::vector<std::string> >(frame["STBLG"]);
std::vector<std::string> ReversalIndicator(Reversal_Accounting_Transaction_ID.size()) ;
if (Reversal_Accounting_Transaction_ID.size() == 0) {
return ReversalIndicator;
}
int dfSize = Reversal_Accounting_Transaction_ID.size();
for (int i = 0; i < dfSize; ++i) {
if (Reversal_Accounting_Transaction_ID[i] != "") {
for (int j = 1; j < dfSize; ++j) {
if(Accounting_Transaction_ID[j]== Reversal_Accounting_Transaction_ID[i]){
ReversalIndicator[i]="Yes";
break;
}
else if( (j== dfSize -1) ){
ReversalIndicator[i]="No";
}
}
}
else{
ReversalIndicator[i]="No";
}
}
return ReversalIndicator;
}
')```
```df$reversal=reversals(df)```
You are traversing your data frame for every row of your data frame, i.e. you have something like 6m x 6m operations (O(N^2)). That can take quite a while. However, you can go from O(N^2) to O(N) at the expense of some memory. Without any sample data I cannot test this, so I am providing some pseudo code only:
create empty set data structure
for each row in df:
Add Reversal_Accounting_Transaction_ID to set
for each row in df:
if Accounting_Transaction_ID can be found in set
ReversalIndicator = "Yes"
Based on Ralphs answer
Not sure if I need to allocate the set a size at the start though?
Rcpp::cppFunction('
std::vector<std::string> reversals(DataFrame frame)
{
std::vector<std::string> Accounting_Transaction_ID = as<std::vector<std::string> >(frame["BELNR"]);
std::vector<std::string> Reversal_Accounting_Transaction_ID = as<std::vector<std::string> >(frame["STBLG"]);
std::vector<std::string> ReversalIndicator(Reversal_Accounting_Transaction_ID.size()) ;
std::set<std::string> uniqueTransID;
if (Reversal_Accounting_Transaction_ID.size() == 0) {
return ReversalIndicator;
}
int dfSize = Reversal_Accounting_Transaction_ID.size();
for (int i = 0; i < dfSize; ++i) {
uniqueTransID.insert(Accounting_Transaction_ID[i]);
}
for (int i = 0; i < dfSize; ++i) {
if (Reversal_Accounting_Transaction_ID[i] !=""){
ReversalIndicator[i]="No";
continue;
}
if (uniqueTransID.find(Reversal_Accounting_Transaction_ID[i]) != uniqueTransID.end()) {
ReversalIndicator[i]="Yes";
}
else{
ReversalIndicator[i]="No";
}
}
return ReversalIndicator;
}
')```

About KMP algorithm preprocessing function implementation

just try to implement a KMP algorithm, but when I try to check on the Internet, it turns out there are two different versions here:
Solution 1:
function computeLPSArray(str){
var j = -1, i = 0;
var arr = [];
arr[0] = j;
while(i < str.length){
if(j == -1||str[i]==str[j]){
i++;
j++;
arr[i] = j;
} else {
j = arr[j];
}
}
return arr;
}
Solution 2:
function computeLPSArray(pat){
var lps = [];
var len = 0, i;
lps[0] = 0;
i = 1;
while(i < pat.length){
if(pat[i] == pat[len]){
len++;
lps[i] = len;
i++;
} else {
if(len != 0){
len = lps[len-1];
} else {
lps[i++] = 0;
}
}
}
return lps;
}
The solution2 came from geeksforgeeks. Why not first solution?
Is there any corner case will failed when I use the Solution1?
Thx...
Not really - both versions can be used to perform the same tasks. The usage of the failure links array is a bit different, but the complexity of the algorithm is the same and both approaches are correct.
In one of the approaches the fail link is the length of longest proper suffix that is also a proper prefix(this would be version 2), while in the first version it is 1 less. As you can figure the two arrays are equivalent and can be converted from one to the other by adding/subtracting 1.

The method 'Equals' is not supported

public List<Health_Scheme_System.Employee> GetPenEmployeeTable()
{
Health_Scheme_System.Health_Scheme_SystemDB db = new Health_Scheme_System.Health_Scheme_SystemDB();
var x = (from c in db.Employees
where c.Pensioners.Equals (1)
select c);
return x.ToList();
}
//Selecting multiple columns from an HR view table together with the scheme name of scheme.
public List<EmployeesX> GetPensioners()
{
Health_Scheme_System.Health_Scheme_SystemDB db = new Health_Scheme_System.Health_Scheme_SystemDB();
List<Health_Scheme_System.EmployeeDirectory> listEmployeeView = GetPenEmployeeView();
List<Health_Scheme_System.Employee> listEmployeeTable = GetPenEmployeeTable();
List<Health_Scheme_System.Scheme> listSchemes = GetSchemes();
List<EmployeesX> listOfEmployees = new List<EmployeesX>();
//checking for comparision of getemployeeview to getemployee table and then to getschemes
//Then display the scheme name if they are similar.
for (int i = 0; i < listEmployeeView.Count; i++)
{
EmployeesX emp = new EmployeesX();
emp.ID_NO = listEmployeeView[i].ID_NO;
emp.FIRST_NAME = listEmployeeView[i].FIRST_NAME;
emp.LAST_NAME = listEmployeeView[i].LAST_NAME;
emp.LOCATION_CODE = listEmployeeView[i].LOCATION_CODE;
for (int j = 0; j < listEmployeeTable.Count; j++)
{
if (listEmployeeTable[j].EmployeeIDCard == listEmployeeView[i].ID_NO)
{
emp.Pensioners = listEmployeeTable[j].Pensioners;
for (int k = 0; k < listSchemes.Count; k++)
{
if (listEmployeeTable[j].SchemeID == listSchemes[k].SchemeID)
{
emp.SCHEME_NAME = listSchemes[k].Name;
emp.START_DATE = listEmployeeTable[j].StartSchemeDate;
}
}
}
}
listOfEmployees.Add(emp);
}
return listOfEmployees;
}
How can I make the same method with using .equals??
Have you tried this:
var x = (from c in db.Employees
where c.Pensioners == 1
select c)
Additional info:
If you use a method on an object in a linq query subsonic needs to know how to translate that into pur SQL code. That does not work by default and must be implemented for every known method on every supported type for every dataprovider (if differs from default implementation). So there is a bunch of work to do for subsonic.
A good starting point for knowning what's supported and what not is the TSqlFormatter class. Have a look at protected override Expression VisitMethodCall(MethodCallExpression m)
https://github.com/subsonic/SubSonic-3.0/blob/master/SubSonic.Core/Linq/Structure/TSqlFormatter.cs
There is already an implementation for Equals
else if (m.Method.Name == "Equals")
{
if (m.Method.IsStatic && m.Method.DeclaringType == typeof(object))
{
sb.Append("(");
this.Visit(m.Arguments[0]);
sb.Append(" = ");
this.Visit(m.Arguments[1]);
sb.Append(")");
return m;
}
else if (!m.Method.IsStatic && m.Arguments.Count == 1 && m.Arguments[0].Type == m.Object.Type)
{
sb.Append("(");
this.Visit(m.Object);
sb.Append(" = ");
this.Visit(m.Arguments[0]);
sb.Append(")");
return m;
}
else if (m.Method.IsStatic && m.Method.DeclaringType == typeof(string))
{
//Note: Not sure if this is best solution for fixing side issue with Issue #66
sb.Append("(");
this.Visit(m.Arguments[0]);
sb.Append(" = ");
this.Visit(m.Arguments[1]);
sb.Append(")");
return m;
}
}
I suppose Prnsioners is an integer type so you basically have to add another else if and recomplie subsonic.
This should work but I haven't tested it.
else if (!m.Method.IsStatic && m.Method.DeclaringType == typeof(int))
{
sb.Append("(");
this.Visit(m.Arguments[0]);
sb.Append(" = ");
this.Visit(m.Arguments[1]);
sb.Append(")");
return m;
}
(or you can try the == approach like in the example on the top).

Resources