Сделайте столбец или ячейки доступными только для чтения с помощью EPPlus

Есть ли способ сделать столбец или группу ячеек заблокированными или только для чтения с помощью EPPlus? Я пробовал приведенный ниже код как отдельно, так и вместе, но, похоже, ни один из них не дал желаемого эффекта. Либо весь рабочий лист заблокирован (если я включу оператор IsProtected), либо вообще ничего.

        ws.Protection.IsProtected = true;
        ws.Column(10).Style.Locked = true;

ИЗМЕНИТЬ

Вот весь блок кода с моего контроллера

        FileInfo newFile = new FileInfo("C:\\Users\\" + User.Identity.Name + "\\Desktop" + @"\\ZipCodes.xlsx");

        ExcelPackage pck = new ExcelPackage(newFile);

        var ws = pck.Workbook.Worksheets.Add("Query_" + DateTime.Now.ToString());

        //Headers
        ws.Cells["A1"].Value = "ChannelCode";
        ws.Cells["B1"].Value = "DrmTerrDesc";
        ws.Cells["C1"].Value = "IndDistrnId";
        ws.Cells["D1"].Value = "StateCode";
        ws.Cells["E1"].Value = "ZipCode";
        ws.Cells["F1"].Value = "EndDate";
        ws.Cells["G1"].Value = "EffectiveDate";
        ws.Cells["H1"].Value = "LastUpdateId";
        ws.Cells["J1"].Value = "ErrorCodes";
        ws.Cells["K1"].Value = "Status";
        ws.Cells["I1"].Value = "Id";

        //Content
        int i = 2;
        foreach (var zip in results)
        {
            ws.Cells["A" + i.ToString()].Value = zip.ChannelCode;
            ws.Cells["B" + i.ToString()].Value = zip.DrmTerrDesc;
            ws.Cells["C" + i.ToString()].Value = zip.IndDistrnId;
            ws.Cells["D" + i.ToString()].Value = zip.StateCode;
            ws.Cells["E" + i.ToString()].Value = zip.ZipCode;
            ws.Cells["F" + i.ToString()].Value = zip.EndDate.ToShortDateString();
            ws.Cells["G" + i.ToString()].Value = zip.EffectiveDate.ToShortDateString();
            ws.Cells["H" + i.ToString()].Value = zip.LastUpdateId;
            ws.Cells["J" + i.ToString()].Value = zip.ErrorCodes;
            ws.Cells["K" + i.ToString()].Value = zip.Status;
            ws.Cells["I" + i.ToString()].Value = zip.Id;

            i++;
        }

        //ws.Protection.IsProtected = true;
        ws.Column(10).Style.Locked = true;

        return new ExcelResult
            {
                FileName = "ZipCodes.xlsx",
                Package = pck
            };

ExcelРезультат

public class ExcelResult : ActionResult
{
    public string FileName { get; set; }
    public ExcelPackage Package { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.Buffer = true;
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=" + FileName);
        context.HttpContext.Response.ContentType = "application/vnd.ms-excel";
        context.HttpContext.Response.BinaryWrite(Package.GetAsByteArray());
    }
}

Второе редактирование

Я попытался защитить рабочий лист, установив для свойства IsProtected значение true, а затем задав для свойства Locked значение false для каждого столбца, кроме последнего. Электронная таблица не только не была доступна только для чтения, но я мог редактировать данные в каждом столбце.

Однако я заметил, что не могу изменить размер самих столбцов, поэтому, возможно, это то, что я делаю. Однако я хотел бы заблокировать каждую ячейку в столбце, чтобы нельзя было вводить новые данные.

        for (int a = 1; a < 10; a++)
        {
            ws.Column(a).Style.Locked = false;
        }
        ws.Protection.IsProtected = true;

person NealR    schedule 23.12.2013    source источник


Ответы (7)


EPPlus может по умолчанию блокировать все ячейки, и в этом случае вам нужно установить атрибут Locked на false для столбцов other, а затем установить для IsProtected значение true.

person richardtallent    schedule 23.12.2013
comment
Только что сделал попытку по этому поводу и добавил в свой пост под Вторым редактированием. Это в принципе то, о чем вы говорили? Если да, можете ли вы взглянуть и посмотреть, не заметите ли вы что-нибудь неуместное? - person NealR; 24.12.2013
comment
В основном, да. Хотя я думаю, вы можете установить свойство Locked сразу для всего листа, а затем переопределить один столбец. Еще одна вещь, которую вам нужно сделать, это установить другие атрибуты атрибута защиты, которые контролируют, что пользователь может и что не может делать с заблокированными ячейками. - person richardtallent; 24.12.2013
comment
Это кажется действительно обратным способом блокировки ячейки. На самом деле, зачем вообще иметь свойство Locked, если его можно использовать только для того, чтобы иметь возможность установить значение false, когда IsProtected установлено значение true? странный.... - person NealR; 24.12.2013
comment
Это соответствует собственной функциональности Excel — защищенный лист только защищает заблокированные ячейки, а ячейки заблокированы по умолчанию. Я бы хотел, чтобы Microsoft разрешила более тонкие элементы управления, такие как несколько типов защиты для разных диапазонов на одном листе, но, увы, это не так. - person richardtallent; 25.12.2013
comment
Не могли бы вы ответить на такой же вопрос ..? stackoverflow.com/questions/20544041/ - person ; 26.12.2013

Я добавляю два рабочих листа, и мне нужно защитить все столбцы, кроме столбца в третьем индексе.

Это сработало для меня :)

worksheet2.Cells["A1"].LoadFromDataTable(dt_Data, true); //------load data from datatable
worksheet2.Protection.IsProtected = true; //--------Protect whole sheet
worksheet2.Column(3).Style.Locked = false; //-------Unlock 3rd column
person Harmeet Singh Bhamra    schedule 07.10.2014
comment
Я добавляю пароль, чтобы никто не мог изменить содержимое worksheet2.Protection.SetPassword(Guid.NewGuid().ToString()); - person dpfauwadel; 07.06.2016

Просто подумал, что опубликую решение на случай, если оно поможет кому-то еще. Мне пришлось сделать весь лист защищенным, но установить для атрибута Locked значение false для каждого поля, отличного от Id.

        //Content
        int i = 2;
        foreach (var zip in results)
        {
            //Set cell values
            ws.Cells["A" + i.ToString()].Value = zip.ChannelCode;
            ws.Cells["B" + i.ToString()].Value = zip.DrmTerrDesc;
            ws.Cells["C" + i.ToString()].Value = zip.IndDistrnId;
            ws.Cells["D" + i.ToString()].Value = zip.StateCode;
            ws.Cells["E" + i.ToString()].Value = zip.ZipCode;
            ws.Cells["F" + i.ToString()].Value = zip.EndDate.ToShortDateString();
            ws.Cells["G" + i.ToString()].Value = zip.EffectiveDate.ToShortDateString();
            ws.Cells["H" + i.ToString()].Value = zip.LastUpdateId;
            ws.Cells["I" + i.ToString()].Value = zip.ErrorCodes;
            ws.Cells["J" + i.ToString()].Value = zip.Status;
            ws.Cells["K" + i.ToString()].Value = zip.Id;

            //Unlock non-Id fields
            ws.Cells["A" + i.ToString()].Style.Locked = false;
            ws.Cells["B" + i.ToString()].Style.Locked = false;
            ws.Cells["C" + i.ToString()].Style.Locked = false;
            ws.Cells["D" + i.ToString()].Style.Locked = false;
            ws.Cells["E" + i.ToString()].Style.Locked = false;
            ws.Cells["F" + i.ToString()].Style.Locked = false;
            ws.Cells["G" + i.ToString()].Style.Locked = false;
            ws.Cells["H" + i.ToString()].Style.Locked = false;
            ws.Cells["I" + i.ToString()].Style.Locked = false;
            ws.Cells["J" + i.ToString()].Style.Locked = false;

            i++;
        }

        //Since we have to make the whole sheet protected and unlock each cell 
        //to allow for editing this loop is necessary
        for (int a = 65000 - i; i < 65000; i++)
        {
            //Unlock non-Id fields
            ws.Cells["A" + i.ToString()].Style.Locked = false;
            ws.Cells["B" + i.ToString()].Style.Locked = false;
            ws.Cells["C" + i.ToString()].Style.Locked = false;
            ws.Cells["D" + i.ToString()].Style.Locked = false;
            ws.Cells["E" + i.ToString()].Style.Locked = false;
            ws.Cells["F" + i.ToString()].Style.Locked = false;
            ws.Cells["G" + i.ToString()].Style.Locked = false;
            ws.Cells["H" + i.ToString()].Style.Locked = false;
            ws.Cells["I" + i.ToString()].Style.Locked = false;
            ws.Cells["J" + i.ToString()].Style.Locked = false;                
        }

        //Set worksheet protection attributes
        ws.Protection.AllowInsertRows = true;
        ws.Protection.AllowSort = true;
        ws.Protection.AllowSelectUnlockedCells = true;
        ws.Protection.AllowAutoFilter = true;
        ws.Protection.AllowInsertRows = true;
        ws.Protection.IsProtected = true;
person NealR    schedule 24.12.2013
comment
Вы должны иметь возможность сделать то же самое с этим: ws.Cells.Style.Locked=false;ws.Cells[K].Style.Locked=true;. Это разблокирует все ячейки на листе, а затем заблокирует только ячейки в столбце K. Код (@Softwarehuset делает то же самое, что и второй оператор здесь, и я на самом деле предпочитаю индексировать столбцы по номеру, как это сделал он, но я хотел показать, что вы можете ссылайтесь на них также по буквам. В любом случае, вы можете пропустить весь цикл строк.) - person richardtallent; 25.12.2013
comment
Нужно ли мне по-прежнему защищать весь рабочий лист? Одна из проблем, с которыми мы столкнулись, заключается в том, что кажется, что вы не можете вырезать/вставлять какие-либо строки в защищенный рабочий лист. - person NealR; 27.12.2013
comment
@NealR Я хотел отметить, что вы определили дважды - ws.Protection.AllowInsertRows = true; Это необходимо? - person Imants Volkovs; 14.02.2017

Итак, я имел в виду этот вопрос, и именно так я делаю блокировку.

worksheet.Protection.IsProtected = true;
//I'm creating a template for users to fill in data.These headers
//will come from database tables later on.
//So tableHeaders is an array of strings
for (int i = 1; i <= tableHeaders.Length; i++)
            {
                worksheet.Column(i).Style.Locked = false;
            }
//And then lock the first row.
worksheet.Row(1).Style.Locked = true;
//Additionally don't allow user to change sheet names
excelPackage.Workbook.Protection.LockStructure = true;
person abcdefghiraj    schedule 21.12.2016

сначала заблокируйте весь лист, а затем разблокируйте ячейки, которые вы хотите разблокировать.

workSheet.Protection.IsProtected = true;

workSheet.Cells[2, 3, pocDeatils.CityMaster.Rows.Count + 1, 4].Style.Locked = false;

для более подробной информации см. ссылку ниже: https://epplus.codeplex.com/SourceControl/latest#SampleApp/Sample6.cs

person Prasad Shigwan    schedule 12.01.2017

ws.Column(10).Style.Locked = true;

должен сделать это. пожалуйста, проверьте остальную часть вашего кода на наличие ошибок :)

person Softwarehuset    schedule 23.12.2013
comment
Вроде бы все нормально, насколько я знаю, как пользоваться плагином. Просто добавил весь блок кода в пост, к вашему сведению. - person NealR; 24.12.2013

  1. Чтобы заблокировать определенные столбцы или группы ячеек, вам нужно сначала узнать, какие столбцы вам нужно редактировать. Добавьте эти запятые, разделенные запятыми, в 'new ExcelAddress()', который является вторым параметром [разделение запятыми полезно, когда редактируемые столбцы находятся в другом порядке]

Например: я хочу заблокировать только столбцы M ws.ProtectedRanges.Add(editable, new ExcelAddress(A3:A25,L3:L25,N3:N25));

  1. Затем вторая часть заключается в защите всего рабочего листа ws.Protection.IsProtected = true;
person Sourabh Hebbar    schedule 09.12.2020