question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

using ArrayResizer and ExcelAsyncUtil produces unstable output

See original GitHub issue

Hi all,

I am new to this package. So far everything is good except for the behavior of my formula is a bit unstable when I am dragging the formula across multiple cells. Below is my code:

    `[ExcelFunction(Description = "Get historical fundamental data")]
    public static object FD(
        [ExcelArgument(AllowReference = true, Name = "Ticker")] string ticker,
        [ExcelArgument(AllowReference = true, Name = "Field")] string field,
        [ExcelArgument(AllowReference = true, Name = "Start Date")] string start_date = "",
        [ExcelArgument(AllowReference = true, Name = "End Date")] string end_date = "",
        [ExcelArgument(AllowReference = true, Name = "Period")] string period = "",
        [ExcelArgument(AllowReference = true, Name = "DTS")] string dts = "")
    {
        ExcelReference caller = (ExcelReference)XlCall.Excel(XlCall.xlfCaller);
        string NA = "";

        object asyncResult = ExcelAsyncUtil.Run("FD", new string[] 
                {ticker, field, start_date, end_date, period, dts}, () =>
        {
           
            // a bunch of code to preprocessing to generate the SQL query string

            MySqlConnection conn = GetConnection();
            MySqlCommand cmd = new MySqlCommand(SqlQuery, conn);

            cmd.Parameters.AddWithValue("@Ticker", ticker);

            conn.Open();
            cmd.ExecuteNonQuery();
            DataTable table = new DataTable();
            MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
            adapter.Fill(table);
            conn.Close();

            var rows = table.Rows;
            int rowCount = rows.Count;
            int colCount = table.Columns.Count;
            var result = new object[rowCount, colCount];

            if (result.GetLength(0) == 0)
                return "#No Data";

            for (int i = 0; i < rowCount; i++)
            {
                var row = rows[i];
                int j = 0;
                if (row[0].GetType().Equals(typeof(System.DateTime)))
                {
                    result[i, j] = Convert.ToDateTime(row[j]).ToShortDateString();
                    j = 1;
                }
                for (; j < colCount; j++)
                    result[i, j] = (row[j] == DBNull.Value) ? NA : row[j];
            }

            ArrayResizer.Resize(result, caller);
            return result;
        });

        if (asyncResult.Equals(ExcelError.ExcelErrorNA)) return "#Requesting Data";
        return asyncResult;
    }`

The when I drag my formula across row 2 in my sheet, I got the following output

capture1

for some columns only (strangely, most columns work fine, only a few got problem), you could see it either returns the “-” NA string I defined or only the first row of the returned array.

To test and make sure it is not the issue of SQL execution, I modified the above code to by inserting the

return result.GetLength(0)

before the last nested two for loops. I want to see the number of rows in my “result” array . You could see the UDF now works fine after this change, returning the correct number of rows returned from SQL execution.

capture

My ArrayResizer method is taken directly from https://github.com/Excel-DNA/ExcelDna/blob/master/Distribution/Samples/ArrayResizer.dna Without modification.

For those few columns I circled in blue, if I enter the formula by hand in a new workbook individually using the exact same UDF input argument, they will output the array correctly like most of the other arrays. The problem only appear when I do formula dragging across multiple cells.

Not sure if I have done anything wrongly. Any help is greatly appreciated.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
fricativecommented, May 31, 2018

hi hell-racer,

following the possible workaround suggested, I updated my code a little bit to the following which write directly to excel instead of returning an resized array.

` [ExcelFunction(Description = “Get historical time serie”)] public static object FDH( [ExcelArgument(AllowReference = true, Name = “Ticker”)] string ticker, [ExcelArgument(AllowReference = true, Name = “Field”)] string field, [ExcelArgument(AllowReference = true, Name = “Start Date”)] string start_date = “”, [ExcelArgument(AllowReference = true, Name = “End Date”)] string end_date = “”, [ExcelArgument(AllowReference = true, Name = “Period”)] string period = “”, [ExcelArgument(AllowReference = true, Name = “DTS”)] string dts = “”) { ExcelReference caller = (ExcelReference)XlCall.Excel(XlCall.xlfCaller); int TopLeftRow = caller.RowFirst + 1; int TopLeftCol = caller.ColumnFirst + 1; string NA = “-”;

           // preprocessing code here

            MySqlConnection conn = GetConnection();
            MySqlCommand cmd = new MySqlCommand(SqlQuery, conn);

            cmd.Parameters.AddWithValue("@Ticker", ticker);

            conn.Open();
            cmd.ExecuteNonQuery();
            System.Data.DataTable table = new System.Data.DataTable();
            MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
            adapter.Fill(table);
            conn.Close();

            var rows = table.Rows;
            int rowCount = rows.Count;
            int colCount = table.Columns.Count;
            var result = new object[rowCount, colCount];

            if (result.GetLength(0) == 0)
                return "#No Data";

            for (int i = 0; i < rowCount; i++)
            {
                var row = rows[i];
                int j = 0;
                if (row[0].GetType().Equals(typeof(System.DateTime)))
                {
                    result[i, j] = Convert.ToDateTime(row[j]).ToShortDateString();
                    j = 1;
                }
                for (; j < colCount; j++)
                    result[i, j] = (row[j] == DBNull.Value) ? NA : row[j];
            }
            ExcelAsyncUtil.QueueAsMacro(() =>
            {
                Microsoft.Office.Interop.Excel.Application app = (Microsoft.Office.Interop.Excel.Application) ExcelDnaUtil.Application;
                Worksheet ws = app.ActiveSheet;

                // write the first row of the array into excel
                if (colCount > 1)
                    for (int j = 1; j < colCount; j++)
                        ws.Cells[TopLeftRow, TopLeftCol + j].Value = result[0, j];

                // write second row and onward of the array into excel
                for(int i = 1; i < rowCount; i++)
                    for(int j = 0; j < colCount; j++)
                        ws.Cells[TopLeftRow + i, TopLeftCol + j].Value = result[i,j];
            });
            return result[0, 0];
        });

        if (asyncResult.Equals(ExcelError.ExcelErrorNA)) return "#Requesting Data";
        return asyncResult;
    }`

The result is I successfully get rid of array formula and array resizer (hence realizing the same effect of Bloomberg BDH formula, which is good). However, seems when I drag the formula across cells, the same problem still occurred like the screenshot I originally pasted. Maybe the issue is to do with ExcelAsyncUtil not able to process too many macro in parallel?

0reactions
govertcommented, Jun 9, 2018

Closing this - feel free to re-open if there’s anything else we need to look at.

Read more comments on GitHub >

github_iconTop Results From Across the Web

ExcelAsyncUtil.Run and Resize of the output array
I am using ExcelAsyncUtil.Run() to calculate long-time taking calculations and then would like to resize the output range to the actual size ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found