How do i find the last used column in a row? C#

时间:2016-02-12 20:47:29

标签: c# excel

I have an excel sheet that I am reading. it contains multiple rows (No headers) each row containing a different number of populated columns. i.e. row 1 has data in the first three columns. row 2 has data in the first 140 columns. row 3 has data in the first 32 columns. etc etc.

If I need to find out how many columns row 2 uses (How many contain data), how would I start.

I am teaching myself c sharp at the moment and am jargon illiterate, so please be as "Layman" as possible.

Any help would be greatly appreciated.

Thank you.

Edit ------------------------

Had a quick look through some bookmarks and have a rough idea of the code i used to get the row number containing the columns i need to count. (i cant test as i don't have VS installed at home. so dont take this as gospel, but it seems "approximately" correct, sorry.)

 v = [1 2 3 4 5 6 7];
    inpt_img = imread('A10001.png');
    [out_img , a_out] = image_filtering (v (:,:),inpt_img);

from here i need to find the number of used columns in row CurrentFind.

--------------------Edit-------------------------------- Finally back in the office, This was the code i had to find the row number;

private static Excel.Application HCObjApp = null;
private static Excel.Workbook HCBook = null; 
private static Excel.Worksheet HCSheet = null;

XLApp = new Excel.Application();
HCBook = MyApp.Workbooks.Open(@"WBPATH\WB.exe");
HCSheet = HCBook.Sheets[1];
lastRow = MySheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell).Row; 

Excel.Range range = HCSheet.Columns["A", Type.Missing];

currentFind = range.Find("Australia",HCSheet.Cells[lastrow, 1]);

With Many thanks to @Hambone i found the solution (more accurately i found 0.1% of the solution. Hambone found the rest);

        EHObjApp.Visible = true;

        string ColumnHeader = ResourceDetails.ResourceHolder("Root") + ResourceDetails.ResourceHolder("ResourceFolder") + ResourceDetails.ResourceHolder("ColumnHeaders");
        HCBook = EHObjApp.Workbooks.Open(ColumnHeader);
        HCSheet = HCBook.Worksheets.get_Item(1);
        InputBook = EHObjApp.Workbooks.Open(ResourceDetails.ResourceHolder("Root") + @"\Sales\Output\Zoho_Upload\ZOHOSales.xlsx");
        InputSheet = InputBook.Worksheets.get_Item(1);
        long ExRownumber = HCSheet.Range["A:A"].Find("SalesAustralia").Row + 1;
        Range NewColumns = InputSheet.Range["A1:A" + InputSheet.UsedRange.Columns.Count];

This will find the last used column in the row.

You guys have been an amazing help!

Thank you

----------Addition--------------- When finding the smaller column numbers, i.e. rows of 30 or 31 columns etc, this worked fine. I ran into an issue when trying to find the larger numbers, i.e. rows of 140 columns. Changing xlToLeft back to xlUp solved this issue.

Thought i would add this in for anyone that requires this solution in the future.

2 个答案:

答案 0 :(得分:3)

我已经看到在VBA中使用这种技术来查找范围中的最后一行,并且它很好地接口到C#:

class UserPhoneNumberView(FormView):
    form_class = UserPhoneNumberForm
    template_name = "get_user_phonenumber.html"

    def form_valid(self, form):
        phonenumber = self.request.POST.get("mobile_number")
        unique = self.request.POST.get("unique")
        url = "http://example.com/"+unique
        response = HttpResponse("", status=302)
        body = "See this url: "+url
        nonhttp_url = "sms:"+phonenumber+"?body="+body
        response['Location'] = nonhttp_url
        return response

此时Excel.Range ur = HCSheet.UsedRange; Excel.Range r = HCSheet.Cells[2, ur.Columns.Count]; r = r.get_End(Excel.XlDirection.xlToLeft); 的值将是第2行中最后一个填充的单元格。要获得除2之外的行,您只需更改r索引器中的第一个参数。

为了证明它有效,你可以这样做:

.Cells

要查找最后一个列号,我认为这是您的问题:

r.Value = "Gotcha";

答案 1 :(得分:-1)

Excel自动化是一项雄心勃勃的尝试,只需从任何.NET语言开始。在前面,Web上的许多示例都没有考虑正确释放内存,并且在不需要时将使用对垃圾收集器的调用。在下面的示例代码中,方法UsedRowsColumns不需要对垃圾收集器进行任何调用,因为我遵循了我所谓的two dot rule(其中99.99%的时间释放所有对象,但正如您将看到的并不总是如此)。你会注意到点击该页面上的kevininstructor,因为双点规则将失败,我在更改为kareninstructor时将其更改。

  • 下面显示的类,我会测试它们,如果它们符合您的需要,将它们放入一个类项目中,所以如果您想在其他项目中使用此代码,您只需添加对这些项目的引用,而不是将代码从项目复制到项目
  • button1中的Console.WriteLine使用VS2015语法,如果使用较低版本,则需要进行此类调整Console.WriteLine(“{0} {1}”,....

与UsedRowsColumns方法不同,LastColumnForRow(应该回答你的问题)必须做一些额外的工作,因为垃圾收集器需要被调用但不能在同一个方法中调用,所以我设置了一个方法CallGarbageCollector,它在调用之后to LastColumnForRow我调用它来释放Range xlColumns,即使在执行双点规则时它也不会释放。

要测试的表单代码,button1调用以获取第2行的最后一列。

using System;
using System.Windows.Forms;
using System.IO;

namespace UsedRowsCols
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private string fileName = Path.Combine(
            AppDomain.CurrentDomain.BaseDirectory, "Demo.xlsx");
        private string sheetName = "Sheet1";
        /// <summary>
        /// Get last row and last column for a worksheet.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            ExcelUsed eu = new ExcelUsed();
            ExcelLast results = eu.UsedRowsColumns(fileName, sheetName);
            // send results to Visual Studio Output window
            Console.WriteLine($"{results.Row} {results.Column}");
        }

        /// <summary>
        /// Get last used column for a specific row
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            ExcelUsed eu = new ExcelUsed();
            try
            {
                int results = eu.LastColumnForRow(fileName, sheetName,2);
                // send results to Visual Studio Output window
                Console.WriteLine(results);
            }
            finally
            {
                eu.CallGarbageCollector();
            }
        }
    }
}

负责获取上面button1中已使用列的类,并使用上面button2中的行和列。

using System;
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.IO;

namespace UsedRowsCols
{
    public class ExcelUsed
    {
        /// <summary>
        /// Get last used column for a row
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="sheetName"></param>
        /// <param name="row"></param>
        /// <returns></returns>
        public int LastColumnForRow(string fileName, string sheetName, int row)
        {
            int lastColumn = -1;

            if (File.Exists(fileName))
            {
                Excel.Application xlApp = null;
                Excel.Workbooks xlWorkBooks = null;
                Excel.Workbook xlWorkBook = null;
                Excel.Worksheet xlWorkSheet = null;
                Excel.Sheets xlWorkSheets = null;

                xlApp = new Excel.Application();
                xlApp.DisplayAlerts = false;

                xlWorkBooks = xlApp.Workbooks;
                xlWorkBook = xlWorkBooks.Open(fileName);

                xlApp.Visible = false;

                xlWorkSheets = xlWorkBook.Sheets;

                for (int x = 1; x <= xlWorkSheets.Count; x++)
                {
                    xlWorkSheet = (Excel.Worksheet)xlWorkSheets[x];

                    if (xlWorkSheet.Name == sheetName)
                    {
                        Excel.Range xlCells = null;
                        xlCells = xlWorkSheet.Cells;

                        Excel.Range workRange = xlCells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell);

                        Excel.Range xlColumns = xlWorkSheet.Columns;

                        int count = xlColumns.Count;

                        Marshal.FinalReleaseComObject(xlColumns);
                        xlColumns = null;

                        Excel.Range xlLastRange = (Excel.Range)xlWorkSheet.Cells[row, count];
                        Excel.Range xlDirRange = xlLastRange.End[Excel.XlDirection.xlToLeft];

                        Marshal.FinalReleaseComObject(xlLastRange);
                        xlLastRange = null;

                        lastColumn = xlDirRange.Column;
                        Marshal.FinalReleaseComObject(xlDirRange);
                        xlDirRange = null;

                        Marshal.FinalReleaseComObject(workRange);
                        workRange = null;

                        Marshal.FinalReleaseComObject(xlCells);
                        xlCells = null;

                        break;
                    }

                    Marshal.FinalReleaseComObject(xlWorkSheet);
                    xlWorkSheet = null;

                }

                xlWorkBook.Close();
                xlApp.UserControl = true;
                xlApp.Quit();

                Release(xlWorkSheets);
                Release(xlWorkSheet);
                Release(xlWorkBook);
                Release(xlWorkBooks);
                Release(xlApp);

                return lastColumn;

            }
            else
            {
                throw new Exception("'" + fileName + "' not found.");
            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileName">file to get information form</param>
        /// <param name="sheetName">valid sheet name to get last row and column</param>
        /// <returns>ExcelLast</returns>
        public ExcelLast UsedRowsColumns(string fileName, string sheetName)
        {

            int RowsUsed = -1;
            int ColsUsed = -1;

            if (File.Exists(fileName))
            {
                Excel.Application xlApp = null;
                Excel.Workbooks xlWorkBooks = null;
                Excel.Workbook xlWorkBook = null;
                Excel.Worksheet xlWorkSheet = null;
                Excel.Sheets xlWorkSheets = null;

                xlApp = new Excel.Application();
                xlApp.DisplayAlerts = false;

                xlWorkBooks = xlApp.Workbooks;
                xlWorkBook = xlWorkBooks.Open(fileName);

                xlApp.Visible = false;

                xlWorkSheets = xlWorkBook.Sheets;

                for (int x = 1; x <= xlWorkSheets.Count; x++)
                {
                    xlWorkSheet = (Excel.Worksheet)xlWorkSheets[x];

                    if (xlWorkSheet.Name == sheetName)
                    {
                        Excel.Range xlCells = null;
                        xlCells = xlWorkSheet.Cells;

                        Excel.Range workRange = xlCells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell);

                        RowsUsed = workRange.Row;
                        ColsUsed = workRange.Column;

                        Marshal.FinalReleaseComObject(workRange);
                        workRange = null;


                        Marshal.FinalReleaseComObject(xlCells);
                        xlCells = null;

                        break;
                    }

                    Marshal.FinalReleaseComObject(xlWorkSheet);
                    xlWorkSheet = null;

                }

                xlWorkBook.Close();
                xlApp.UserControl = true;
                xlApp.Quit();


                Release(xlWorkSheets);
                Release(xlWorkSheet);
                Release(xlWorkBook);
                Release(xlWorkBooks);
                Release(xlApp);

                return new ExcelLast() { Row = RowsUsed, Column = ColsUsed };

            }
            else
            {
                throw new Exception("'" + fileName + "' not found.");
            }
        }
        public void CallGarbageCollector()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();

        }
        private void Release(object sender)
        {
            try
            {
                if (sender != null)
                {
                    Marshal.ReleaseComObject(sender);
                    sender = null;
                }
            }
            catch (Exception)
            {
                sender = null;
            }
        }
    }
    public class ExcelLast
    {
        /// <summary>
        /// Last used row in specific sheet
        /// </summary>
        public int Row { get; set; }
        /// <summary>
        /// Last used column in specific sheet
        /// </summary>
        public int Column { get; set; }
    }
}