惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Vulnerabilities – Threatpost
U
Unit 42
F
Fortinet All Blogs
aimingoo的专栏
aimingoo的专栏
P
Proofpoint News Feed
F
Full Disclosure
月光博客
月光博客
Engineering at Meta
Engineering at Meta
博客园_首页
The Register - Security
The Register - Security
G
Google Developers Blog
The Cloudflare Blog
博客园 - Franky
K
Kaspersky official blog
A
Arctic Wolf
Scott Helme
Scott Helme
C
Cisco Blogs
Hugging Face - Blog
Hugging Face - Blog
C
Check Point Blog
NISL@THU
NISL@THU
AI
AI
D
DataBreaches.Net
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Stack Overflow Blog
Stack Overflow Blog
Project Zero
Project Zero
The GitHub Blog
The GitHub Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
量子位
Vercel News
Vercel News
T
Tor Project blog
P
Privacy International News Feed
D
Docker
I
Intezer
L
LangChain Blog
P
Proofpoint News Feed
Security Latest
Security Latest
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
博客园 - 聂微东
AWS News Blog
AWS News Blog
Martin Fowler
Martin Fowler
P
Privacy & Cybersecurity Law Blog
V
V2EX
Last Week in AI
Last Week in AI
C
Cybersecurity and Infrastructure Security Agency CISA
The Hacker News
The Hacker News
T
Tenable Blog
Blog — PlanetScale
Blog — PlanetScale
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog

博客园 - 反骨少年

cursor使用 wpf 进度条 https://docs.ultralytics.com/zh/tasks/detect/#export 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 vue 前端导出excel vue+.netCore 下载导出文件 SVN提交过滤忽略的文件 博文阅读密码验证 - 博客园 OpenTelemetry 博文阅读密码验证 - 博客园 vue3+ElementPlus 后台布局搭建 IdentityServer4 canal管理 数据同步 Canal数据同步Kafka Xcode的思想,以及能让我学习的规范 阿里云的CICD
通过outxml 复制sheet ,不完整
反骨少年 · 2025-04-23 · via 博客园 - 反骨少年
    internal class Program
    {
        static void Main(string[] args)
        {
            //CopySheet(@"D:\Works\2025-03-24 8D\2025-03-24\test.xlsx", "Sheet1", "8D表格 Copy");
            //CopySheet(@"D:\Works\2025-03-24 8D\2025-03-24\KP_TEMPLATE.xlsx", "8D表格", "8D表格 Copy");
            CopySheet(@"D:\Works\2025-03-24 8D\2025-03-24\开平依利安达-8D不合格 VCAR_for panasonic (003) .xlsx", "8D表格", "8D表格 Copy");
            Console.WriteLine("Hello World!");
        }

        static void CopySheet(string file, string sheetName, string newSheetName)
        {
            MemoryStream stream = new MemoryStream();
            byte[] buff = File.ReadAllBytes(file);
            stream.Write(buff, 0, buff.Length);

            SpreadsheetDocument doc = SpreadsheetDocument.Open(stream, true);
            Sheet sheetRelation = null;
            uint maxSheetId = 0;
            uint sourceSheetIndex = 0;
            uint maxSheetCount = 0;
            foreach (OpenXmlElement s in doc.WorkbookPart.Workbook.Sheets)
            {
                if (s is Sheet st)
                {
                    if (st.Name?.Value == sheetName)
                    {
                        sheetRelation = st;
                        sourceSheetIndex = maxSheetCount;
                    }

                    //记录最大id
                    if (st.SheetId?.Value != null)
                    {
                        if (st.SheetId.Value > maxSheetId)
                            maxSheetId = st.SheetId.Value;
                    }
                    maxSheetCount++;
                }
            }

            if (sheetRelation == null)
                throw new Exception("sheet not found");

            WorksheetPart sheetPart = doc.WorkbookPart.GetPartById(sheetRelation.Id) as WorksheetPart;
            Worksheet sheet = sheetPart.Worksheet;

            WorksheetPart newSheetPart = doc.WorkbookPart.AddNewPart<WorksheetPart>();
            newSheetPart.Worksheet = new Worksheet(sheet.OuterXml);
            SheetView sheetView = (SheetView?)newSheetPart.Worksheet.SheetViews?.Elements().FirstOrDefault();
            if (sheetView != null && sheetView.TabSelected != null)
            {
                sheetView.TabSelected = false;
            }

            var listNewParts = new List<OpenXmlPart>();
            foreach (IdPartPair idPart in sheetPart.Parts)
            {
                OpenXmlPart openxmlPart = null;
                if (idPart.OpenXmlPart is EmbeddedObjectPart)
                {
                    openxmlPart = newSheetPart.AddNewPart<EmbeddedObjectPart>(idPart.OpenXmlPart.ContentType, idPart.RelationshipId);
                }
                else if (idPart.OpenXmlPart is VmlDrawingPart)
                {
                    openxmlPart = newSheetPart.AddNewPart<VmlDrawingPart>(idPart.OpenXmlPart.ContentType, idPart.RelationshipId);
                    listNewParts.Add(openxmlPart);
                    foreach (IdPartPair vmlChildPart in idPart.OpenXmlPart.Parts)
                    {
                        openxmlPart.CreateRelationshipToPart(vmlChildPart.OpenXmlPart, vmlChildPart.RelationshipId);
                    }
                }
                else if (idPart.OpenXmlPart is DrawingsPart)
                {
                    openxmlPart = newSheetPart.AddNewPart<DrawingsPart>(idPart.OpenXmlPart.ContentType, idPart.RelationshipId);
                    foreach (IdPartPair drawingChildPart in idPart.OpenXmlPart.Parts)
                    {
                        openxmlPart.CreateRelationshipToPart(drawingChildPart.OpenXmlPart, drawingChildPart.RelationshipId);
                    }
                    listNewParts.Add(openxmlPart);
                }
                else if (idPart.OpenXmlPart is SpreadsheetPrinterSettingsPart)
                {
                    openxmlPart = newSheetPart.AddNewPart<SpreadsheetPrinterSettingsPart>(idPart.OpenXmlPart.ContentType, idPart.RelationshipId);
                }
                else if (idPart.OpenXmlPart is WorksheetThreadedCommentsPart)
                {
                    openxmlPart = newSheetPart.AddNewPart<WorksheetThreadedCommentsPart>(idPart.OpenXmlPart.ContentType, idPart.RelationshipId);
                }
                else if (idPart.OpenXmlPart is WorksheetCommentsPart)
                {
                    openxmlPart = newSheetPart.AddNewPart<WorksheetCommentsPart>(idPart.OpenXmlPart.ContentType, idPart.RelationshipId);
                }
                // else if (idPart.OpenXmlPart is ImagePart)
                // {
                //     openxmlPart = newSheetPart.AddNewPart(idPart.OpenXmlPart.ContentType, idPart.RelationshipId);
                // }

                if (openxmlPart != null)
                    openxmlPart.FeedData(idPart.OpenXmlPart.GetStream());
                else
                    openxmlPart = idPart.OpenXmlPart;
                newSheetPart.CreateRelationshipToPart(openxmlPart, idPart.RelationshipId);
            }

            ResetOleId(sheet, newSheetPart.Worksheet, listNewParts);
            if (newSheetPart.Parts.Any(d => d.OpenXmlPart is WorksheetThreadedCommentsPart) &&
                newSheetPart.Parts.Any(d => d.OpenXmlPart is WorksheetCommentsPart))
            {
                ResetCommentId(newSheetPart.Parts.First(d => d.OpenXmlPart is WorksheetCommentsPart).OpenXmlPart as WorksheetCommentsPart,
                    newSheetPart.Parts.First(d => d.OpenXmlPart is WorksheetThreadedCommentsPart).OpenXmlPart as WorksheetThreadedCommentsPart);
            }

            Sheet newSheetRelation = new Sheet();
            newSheetRelation.SheetId = (uint)(maxSheetId + 1);
            newSheetRelation.Id = doc.WorkbookPart.GetIdOfPart(newSheetPart);
            newSheetRelation.Name = newSheetName;
            doc.WorkbookPart.Workbook.Sheets.AppendChild(newSheetRelation);

            doc.Save();

            stream.Seek(0, SeekOrigin.Begin);
            buff = new byte[stream.Length];
            stream.Read(buff, 0, buff.Length);
            stream.Close();
            File.WriteAllBytes($@"{Path.GetDirectoryName(file)}\{Path.GetFileNameWithoutExtension(file)}-Copy{Path.GetExtension(file)}", buff);
        }

        static void ResetOleId(Worksheet sheetOld, Worksheet sheetNew, List<OpenXmlPart> newParts)
        {
            uint maxOleId = 0;
            OleObjects oles = sheetOld.Elements<OleObjects>().FirstOrDefault();
            if (oles != null)
            {
                var ids = oles.Elements().Select(d => d.Descendants<OleObject>().FirstOrDefault()?.ShapeId?.Value).Where(d => d != null).Select(d => d.Value);
                if (ids.Any())
                {
                    maxOleId = ids.Max();
                }
            }

            if (maxOleId < 1)
                return;

            var dic = new Dictionary<uint, uint>();
            foreach (AlternateContent alternateContent in sheetNew.Elements<DocumentFormat.OpenXml.Spreadsheet.OleObjects>().Last()?.Elements<AlternateContent>())
            {
                foreach (OleObject oleObject in alternateContent.Descendants<OleObject>())
                {
                    if (oleObject.ShapeId == null)
                        continue;

                    if (dic.ContainsKey(oleObject.ShapeId.Value))
                    {
                        oleObject.ShapeId = dic[oleObject.ShapeId.Value];
                    }
                    else if (oleObject.ShapeId <= maxOleId)
                    {
                        maxOleId = maxOleId * 2;
                        dic.Add(oleObject.ShapeId.Value, maxOleId);
                        oleObject.ShapeId = maxOleId;
                    }
                }
            }

            foreach (OpenXmlPart part in newParts)
            {
                Stream stream = part.GetStream();
                string str = GetStreamString(stream);
                foreach (KeyValuePair<uint, uint> item in dic)
                {
                    str = str.Replace($"s{item.Key}", $"s{item.Value}");
                    str = str.Replace($"id=\"{item.Key}\"", $"id=\"{item.Value}\"");
                }

                stream.Seek(0, SeekOrigin.Begin);
                stream.Write(Encoding.UTF8.GetBytes(str));
                stream.Close();
            }
        }

        static void ResetCommentId(WorksheetCommentsPart commentsPart, WorksheetThreadedCommentsPart threadedCommentsPart)
        {
            if (commentsPart.Comments.CommentList == null)
                return;

            var dic = new Dictionary<string, string>();
            foreach (Comment comment in commentsPart.Comments.CommentList.Elements())
            {
                try
                {
                    OpenXmlAttribute att = comment.GetAttribute("uid", "http://schemas.microsoft.com/office/spreadsheetml/2014/revision");
                    string id = att.Value;
                    string newId = Guid.NewGuid().ToString("B").ToUpper();

                    OpenXmlAttribute attNew = new OpenXmlAttribute("xr", "uid", "http://schemas.microsoft.com/office/spreadsheetml/2014/revision", newId);
                    comment.RemoveAttribute("uid", "http://schemas.microsoft.com/office/spreadsheetml/2014/revision");
                    comment.SetAttribute(attNew);
                    dic.Add(id, newId);
                }
                catch (Exception e)
                {
                    continue;
                }
            }

            foreach (ThreadedComment comment in threadedCommentsPart.ThreadedComments.Elements())
            {
                try
                {
                    if (comment.Id == null)
                        continue;

                    if (dic.ContainsKey(comment.Id.Value))
                        comment.Id = dic[comment.Id.Value];
                }
                catch (Exception e)
                {
                    continue;
                }
            }
        }


        static string GetStreamString(Stream stream)
        {
            stream.Seek(0, SeekOrigin.Begin);
            byte[] buff = new byte[stream.Length];
            stream.Read(buff, 0, buff.Length);
            return Encoding.UTF8.GetString(buff);

        }
    }