【问题标题】:Make column or cells readonly with EPPlus使用 EPPlus 将列或单元格设为只读
【发布时间】:2013-12-23 22:00:09
【问题描述】:

有没有办法使用 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;

【问题讨论】:

    标签: c# .net asp.net-mvc-3 excel epplus


    【解决方案1】:

    我要添加两个工作表,需要保护除第三个索引上的列之外的所有列。

    这对我有用:)

    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
    

    【讨论】:

    • 我添加密码以确保没有人不能更改内容 worksheet2.Protection.SetPassword(Guid.NewGuid().ToString());
    【解决方案2】:

    EPPlus 可能默认锁定 所有 单元格,在这种情况下,您需要将 other 列的 Locked 属性设置为 false,然后设置被保护到true

    【讨论】:

    • 刚刚根据这个做了一个尝试,并将其添加到我的“第二次编辑”下的帖子中。你说的基本就是这个吗?如果是这样,您可以看一下,看看您是否发现任何不合适的地方?
    • 基本上,是的。虽然我 认为 您可以一次为整个工作表设置 Locked 属性,然后覆盖一列。您需要做的另一件事是设置 Protection 属性的其他属性,这些属性控制用户可以对锁定的单元格做什么和不能做什么。
    • 这似乎是一种能够锁定单元格的倒退方式。事实上,当IsProtected 设置为true 时,如果它的唯一用途是能够设置为false,为什么还要设置Locked 属性?奇怪....
    • 这与 Excel 自身的功能相匹配——受保护的工作表 保护“锁定”单元格,默认情况下单元格被锁定。我希望微软能够允许更细粒度的控制,例如在同一张表中为不同范围提供多种类型的保护,但可惜事实并非如此。
    • 你会回答同样的问题吗..? stackoverflow.com/questions/20544041/…
    【解决方案3】:

    只是想我会发布解决方案,以防它帮助其他人。我必须将整个工作表设置为受保护,但将每个非Id 字段的Locked 属性设置为false。

            //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;
    

    【讨论】:

    • 你应该可以用这个来完成同样的事情:"ws.Cells.Style.Locked=false;ws.Cells["K"].Style.Locked=true;"。这会解锁工作表上的所有单元格,然后只锁定 K 列中的单元格。(@Softwarehuset 的代码与此处的第二条语句相同,我实际上更喜欢像他那样按数字索引列,但我想告诉你可以也可以通过字母引用它们。无论哪种方式,您都可以跳过所有行循环的内容。)
    • 我还需要保护整个工作表吗?我们遇到的问题之一是您似乎无法将任何行剪切/粘贴到受保护的工作表中。
    • @NealR 我想提一下,您已经定义了两次 - ws.Protection.AllowInsertRows = true;需要吗?
    【解决方案4】:

    所以我指的是这个问题,这就是我进行锁定的方式。

    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;
    

    【讨论】:

      【解决方案5】:

      先锁定整个工作表,然后解锁您要解锁的单元格。

      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

      【讨论】:

        【解决方案6】:
        ws.Column(10).Style.Locked = true;
        

        应该这样做。请检查其余代码是否有错误:)

        【讨论】:

        • 一切似乎都很好,就我如何知道如何使用该插件而言。刚刚将整个代码块添加到帖子中,仅供参考。
        【解决方案7】:
        1. 为了锁定某些列或单元格组,您首先需要知道哪些列需要是可编辑的。在第二个参数 'new ExcelAddress()' 中添加逗号分隔[当可编辑的列顺序不同时,逗号分隔很有用]

        例如:我只想锁定列 M ws.ProtectedRanges.Add("editable", new ExcelAddress("A3:A25,L3:L25,N3:N25"));

        1. 那么第二部分就是保护整个工作表 ws.Protection.IsProtected = true;

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-07-15
          • 2012-08-22
          • 2012-10-19
          • 2023-04-08
          • 1970-01-01
          • 1970-01-01
          • 2011-09-04
          • 1970-01-01
          相关资源
          最近更新 更多